这个东西研究了好长时间,做下记录。
二分查找的整体结构如下:
while(lo ? hi){
mid = (lo + hi)/2;
if(key ? arr[mid])
//......
else
//......
}
这片文章总结的挺好的,但是我又在解决其他问题的时候遇到不一样的套路,比如这个。主要纠结就在于第一个问号。
经过实验发现,一般我们的搜索都是在完全闭区间中进行搜索的,在这种情况下,第一个问号那里,必须写<=
。但如果写成lo < hi - 1
这种形式,意味着这是半开区间,在这个循环中不会找到hi
这个右边界。而在之前的那种情况下是可以找到右边界的。代码如下:
情况1:
lo <= hi
后面的lo和hi必须要mid加一或者减一的,返回的索引是mid。完整闭区间。
情况2:lo < hi-1
后面的lo和hi必须等于mid,并且返回的索引是lo。去掉了右边界。
情况1的常规代码:
while(lo <= hi){
mid = (lo + hi)/2;
if(x < arr[mid]) hi = mid -1 ;
else if(x > arr[mid]) lo = mid + 1;
else return true;
}
return false;
情况2的常规代码:
while(lo < hi-1){
mid = (lo + hi)/2;
if(x < arr[mid]) hi = mid;
else lo = mid;
}
return arr[lo] == x;
在这个基础上,我还想了如果写了lo < hi
这个条件,会出现什么情况。其实这个,经过实验,也是完全可以查找的,并且是完全闭区间的,但是需要多填一句代码。因为前面第一种情况已经实现了,所以没有必要研究这个,尽管使用上面的两种代码。
二分查找,看似简单,但还是很难写对。