基本的解决方法就是利用二分法:
class Solution {
public:
int search(vector<int>& nums, int target) {
int io=0,hi=nums.size(),mi;
while(io<hi)
{
mi=(io+hi)>>1;
if(nums[mi]==target)return mi;
else if(nums[mi]>target)
hi=mi;
else
io=mi+1;
}
if(nums[mi]==target)return mi;
else return -1;
}
};
二分查找的基本形式比较的固定,主要就是while循环里的那三个判断(也有的方法是取消掉返还mi那个判断,但我觉得好像不太直观容易出错),但还是有几个细节问题:
一 .中间值mi的问题
主要有三种形式:
1.mi=(io+hi)/2
2.mi=io+(hi-io)/2
3.mi=(io+hi)>>1
为了避免出现溢出的情况出现,第2种是比较好的选择
二.查找区间的边界如何选择
边界的选取同时也有三种:
- 左开右闭
(io,hi]
- 左闭右开
[io,hi)
- 左右均闭
[io,hi]
具体如何选择,结合实际问题分析,有时候对同一个问题三种形式都是可行的,但是每一种形式对应的while终止条件,hi,io
的迭代更新和最后的返回值是不尽相同的,下面具体分析一下:
首先对于(io,hi],
基本模板为:
while(io<hi) //终止条件
{
if(if(nums[mi]==target) return mi;
else if(nums[mi]>target)
hi=mi-1; //hi更新
else
io=mi; //io更新
}
对于[io,hi),
基本模板为:
while(io<hi) //终止条件
{
if(if(nums[mi]==target) return mi;
else if(nums[mi]>target)
hi=mi; //hi更新
else
io=mi+1; //io更新
}
对于[io,hi),
基本模板为:
while(io<=hi) //终止条件
{
if(if(nums[mi]==target) return mi;
else if(nums[mi]>target)
hi=mi-1; //hi更新
else
io=mi+1; //io更新
}