下面是一个标准的二分算法及其细节解读:
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left=0,right=nums.size()-1;
int mid=0;
while(left<=right){
mid=((right-left)>>1)+left;
//中间点不用(ight+left)/2防止溢出;
//位运算速度比除法快,可以节省时间
if(nums[mid]==target)
return mid;
else if(nums[mid]>target)
//大小号可以重载为某种排序规则,比如是否是偶数、元素和下标的值是否一致,或者其他实际要求
right=mid-1;
else left=mid+1;
//左右指针不断将不符合target的元素挤出去,同时定位插入位置
//为什么要取mid-1?实际上是为了让两侧指针每次都运动起来
//如果不取mid-1而是mid,随着算法进行,必然只剩left=n和right=n+1指向的两个元素,则left元素也就是mid元素
//如果此时mid<target,那么执行left=mid,两个指针毫无变化,下一轮还是mid=left,将进入死循环
}
return left;//左指针及其左边的值<=target,是为“下界”,因此一定是最终答案,如果必定能查找成功,那么不需要这个返回值
}
};
(点击下方标题即可进入leetcode对应题目页面,全部题解语言为C++,难度为简单)
class Solution {
public:
int missingNumber(vector<int>& nums) {
//记没有出现的数为missnum,则missnum左边的下标和元素值一致,右边的不一致
//寻找缺失的数实际上就是寻找第一个对不上下标的元素
//类比二分查找比大小,实际上这里相当于重载大小符号运算为是否对齐下标
sort(nums.begin(),nums.end());//先排序
int left=0,right=nums.size()-1;
while(left<=right){
int mid=((right-left)>>1)+left;
if(nums[mid]!=mid)
right=mid-1;
else left=mid+1;
}
return left;//由于这里不存在“=”,只有“>”和“<”,因此左指针指向的必定是第一个对不上下标的位置
}
};
解析:二分查找也不一定是线性二分,只要能将元素分为两个可以用映射表示的部分就可以,例如元素的一个单调递增或递减函数。本题的target实际上相当于mid^2函数。
class Solution {
public:
int mySqrt(int x) {
int left=0,right=x;
while(left<=right){