这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战
二分查找基础
二分查找,在很多场景里都会使用到,比如操作系统,MySQL,Hadoop等
- 在有序的数组A中找到给定的数据。操作的数据集是有序的
- 二分查找能应用于任何类型的数据,搜索的集合是相对静态的数据集
面试题
题目1:有序数组中查找目标值
ary = [1, 3, 4, 9, 11, 15, 19, 20,25],target = 8 使用二分查找的方式判断是否是否存在目标数值。
解题思路
二分查找,将有序数据集进行对半分割,并检查每个分区的中间元素,不断循环直到没有区间范围。这个区间范围通过left和right 2个变量来控制。
首先,定义一个区间[left, right] (left :首部位置,right:尾部位置) 开闭原则,我们需要定位的数据是在该区间范围内
第一轮:1, 3, 4, 9, 11, 15, 19, 20,25 left=0 ,right=8,mid=4
ary[mid] > target ,那么 right = mid-1=3
第二轮:1, 3, 4, 9, 11, 15, 19, 20,25 left =0 right = 3,mid= 1
ary[mid] <target,那么 left = mid+1 = 2
第三轮:1, 3, 4, 9, 11, 15, 19, 20,25 left = 2 right = 3 mid=2
left从左向右移,right从右向左移。一旦在middle处找到目标,查找将停止;如果没有找到目标,left和right将重合。
JavaScript 实现
function erfenSearch(ary, target) {
if (ary.length ==0) return false;
let left = 0, right = ary.length;
while (left < right) {
let mid = Math.floor((left + right) / 2);
if(ary[mid] == target){
return true;
} else if (ary[mid] > target) {
right = mid - 1;
} else if (ary[mid] < target) {
left = mid + 1;
}
}
return false;
}
复杂度分析:在实行二分查找时,由于每次我们都会扔掉一半的数据,所以总共只需要 O(lgn)的时间复杂度,空间复杂度是 O(1)。
题目2:查找旋转数组的最小元素(存在重复项)
1, 2, 3, 4, 5的旋转数组为:3, 4, 5, 1, 2要查询找到数组中的最小元素
解题思路:
通过设置三个标志位left,right,mid来减少查询长度。定义3,4,5为原序序列;1,2为翻转子序列。
如果中间元素ary[mid]小于左边元素ary[left],那么证明,中间元素属于翻转子序列。此时最小元素存在于标志位[left ,mid)之间;同理可得,当中间元素大于左边元素时,最小元素存在于标志位[mid,right)直接。
JavaScript 实现
// 寻找最小元素
function findMin(ary) {
let len = ary.length;
if(len == 0)
return -1;
let left = 0, right = len - 1, mid;
while(left < right){
mid = left + (right - left) / 2;
if(ary[mid] > ary[right])
left = mid + 1;
else if(ary[mid] < ary[right])
right = mid;
else
right--;
}
return ary[left];
}