你能写出满分的二分查找算法吗
Posted 纵横千里,捭阖四方
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你能写出满分的二分查找算法吗相关的知识,希望对你有一定的参考价值。
二分查找是分治的经典案例。分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如二分搜索、排序算法(快速排序,归并排序)等等……
任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。问题的规模越小,越容易直接求解,解题所需的计算时间也越少。例如,对于n个元素的排序问题,当n=1时,不需任何计算。n=2时,只要作一次比较即可排好序。n=3时只要作3次比较即可,…。而当n较大时,问题就不那么容易处理了。要想直接解决一个规模较大的问题,有时是相当困难的。
二分查找就是将中间结果与目标进行比较,一次去掉一般,因此二分查找可以说是最简单、最典型的分治了。
废话少说,直接上菜:
public int binarySearch(int[] array, int low, int high, int target)
// 循环
while (low <= high)
int mid = (low + high) /2;
if (array[mid] == target)
return mid ;
else if (array[mid] > target)
// 由于array[mid]不是目标值,因此再次递归搜索时,可以将其排除
high = mid -1;
else
// 由于array[mid]不是目标值,因此再次递归搜索时,可以将其排除
low = mid + 1;
return -1;
这个代码能得多少分?我觉得是70,因为有个很重要的细节没有处理。在计算机中,除的效率非常低,一般可以使用移位来代替,也就是:
将:
int mid = (low + high) /2;
换成
int mid = (low + high)>>1;
如果这样的话,能得到80分,面试官可能会继续问,还会有什么问题。这里的问题是假如low和high很大的话,low + high可能会溢出。因此我们可以这么写:
int mid = low+(high - low)>>1;
只要 low和high没有溢出,上面的mid一定不会溢出。
你觉得可以得到90分,很可惜是0分,因为当你修改代码测试的时候,可能会出现了死循环,例如原始序列是1到8,搜索3的时候就死循环了。这是为什么呢?
这是因为移位的运算符>>优先级比加减要低,所以上面的执行顺序是这样的:
(low+(high - low))>>1
很明显这不是我们预期的。解决方法也很简单,加括号就行了。所以最终的代码就是:
public int binarySearch(int[] array, int low, int high, int target)
while (low <= high)
int mid = low + ((high - low) >> 1);
if (array[mid] == target)
return mid;
else if (array[mid] > target)
// 由于array[mid]不是目标值,因此再次递归搜索时,可以将其排除
high = mid - 1;
else
// 由于array[mid]不是目标值,因此再次递归搜索时,可以将其排除
low = mid + 1;
return -1;
这样的话,面试官就提不出什么问题了,而且上面这个优先级问题很多人只是理解,白纸写也没事,因为很多面试官也不会注意到这里会有死循环的情况。
当然这里还没有考虑元素重复的问题,基本二分查找就是这样了。
以上是关于你能写出满分的二分查找算法吗的主要内容,如果未能解决你的问题,请参考以下文章