这是我参与更文挑战的第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;
};
看一下结果: