算法学习笔记——二分查找

533 阅读2分钟

这是我参与更文挑战的第20天,活动详情查看: 更文挑战

定义

在计算机科学中,二分查找(英语:binary search),也称折半搜索(英语:half-interval search)、对数搜索(英语:logarithmic search),是一种在有序数组中查找某一特定元素的搜索算法。

对数

你可能不记得什么是对数了,但很可能记得什么是幂。log10100相当于问“将多少个10相乘的结果为100”。答案是两个:10 × 10=100。因此,log10100=2。对数运算是幂运算的逆运算

在讨论运行时间时,log指的都是log2使用简单查找法查找元素时,在最糟情况下需要查看每个元素。因此,如果列表包含8个数字,你最多需要检查8个数字。而使用二分查找时,最多需要检查log n个元素。如果列表包含8个元素,你最多需要检查3个元素,因为log 8=3(23= 8)。如果列表包含1024个元素,你最多需要检查10个元素,因为log 1024=10(210=1024)。

解题模板

function binarySearch(list, item) {
    let min = 0;
    let max = list.length - 1;
    while (min <= max) {
        let mid = min + ((max - min) >>> 1); // 先减,可以防止加法运算时溢出
        if (list[mid] == item){
            return mid;
        }
        if (list[mid] > item) {
            max = mid - 1; // 抛去右边
        } else {
            min = mid + 1; // 抛去左边
        }
    }
    return null;
}

真题练习

1. 《剑指 Offer》 二进制中1的个数

请实现一个函数,输入一个整数(以二进制串形式),输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。

示例:

输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。

解题:

var hammingWeight = function(n) {
    let ret = 0;
    for (let i = 0; i < 32; i++) {
        ((n & (1 << i)) !== 0) && ret++; // 1 不断左移和 n 与运算,0和1与运算是0
    }
    return ret;
};

2. leetcode 35.搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

示例 1:

输入: [1,3,5,6], 5
输出: 2

我们来套用一下之前的解题模板:

var searchInsert = function(nums, target) {
    let min = 0;
    let max = nums.length - 1;
    let res = nums.length
    while (min <= max) {
        let mid = min + ((max - min) >>> 1); // 先减,可以防止加法运算时溢出
        if (nums[mid] == target){
            return mid;
        }
        if (nums[mid] > target) {
            max = mid - 1; // 抛去右边
            res = mid; // 没找的话,插入索引向左缩小
        } else {
            min = mid + 1; // 抛去左边
        }
    }
    return res;
};

看一下结果:

image.png