二分查找算法以及面试真题
在一组排好序的数组中,找到所求值的索引。
二分查询思想如下:
取左left
、右边界right
,以及左右边界的中间值index
如果所求的值小于索引index
对应的值:
将右边界right
赋值为index-1
,因为此时index所对应的值是大于所求值num,所以可以直接排除index.
赋值之前:
赋值之后:
如果所求索引的值大于索引值index对应的值:
将左边界left赋值为
index+1`,因为此时index所对应的值是小于所求值num,所以可以直接排除index.
赋值之前:
赋值之后:
理论同上,不再画图,可以看下面二分查找的动画:
如果index对应的值和num的值相等:
所求值对应的索引就是index.
因为在Java语言中。整数之间的乘除加减最后返回值都是整数,所以在求中间索引时不用担心小数问题。
代码如下:
private static int binarySearch(int[] nums, int target) {
// 声明左右边界,以及中间索引
int left = 0, right = nums.length - 1, index;
while (left <= right) {
// 计算中间索引位置
// index = (left + right) / 2;
// 避免数值超过int最大值
// index = left + (right - left) / 2;
index = (left + right) >>> 1;
// 如果相等 代表找到了元素索引
if (nums[index] == target) {
return index;
}
// 如果当前中间值大于要查找的元素 ,让右边界等于索引-1(毕竟索引那里不相等 可以忽略掉)
if (nums[index] > target) {
right = index - 1;
}
// 如果中间值小于要查找的元素,让左边界等于索引+1
if (nums[index] < target) {
left = index + 1;
}
}
return -1;
}
面试题口诀:
1.奇数二分取中间。
2.偶数二分取中间左边。
面试题:
-
有一个有序表为1,5,8,11,19,22,31,35,40,45,48,49,50 。当二分查找值为48的节点时,查找成功需要比较的次数是?
-
在拥有512个元素的数组中二分查找一个数,需要比较的次数最多不超过多少次。
解题方法1:
用512/2/2/2…直到最终等于1,中间除了几次2就是几次。
解题方法2:
2^n = 512 ,求解n的值即可。
解体方法3
: 如果结果为整数,即为最终答案。
如果是小鼠,则舍弃小数部分,整数再加1,为最终结果。