1. 思想
我是习惯了使用【left right 闭区间+ left right 指针结束时同时指向目标值】这种模式。更加灵活的是随着题目变化来调整 left right 的区间含义以及结束条件,但我比较笨,还是只用这一招吧。
固定了模式以后,就要根据题目要求设定好判断条件。
例如这道题,先看题,发现它是有序数组中查找,可以用二分。
查找的目标值就定为缺失数字的下一个元素;然后分析当目标值在 mid 左闭区间和右开区间的条件;最后还要考虑查找的元素是不是一定就在一开始划定的搜索区间中
2. 算法代码
int missingNumber(vector<int>& nums) {
size_t left = 0, right = nums.size()-1;
size_t mid;
// 1. 确定二分查找的目标值:找出缺失值的下一个位置
// 2. 想清楚如果目标值在 mid 的左闭区间([left,mid]),符合什么条件,如果在mid右开区((mid,right]),符合什么条件
// 3. 目标值是否能在 [left, right] 中找到,如果找不到,就要分类讨论
while(left < right){
mid = left + ((right-left)>>1);
if(nums[mid] > mid){
right = mid;
}else{
left = mid + 1;
}
}
// 对于目标值在数组之外的情况要分类讨论,当缺失值是最后一个,那我们的目标值实际上是在数组之外的,所以要另外处理这个特殊情况
if(left==nums.size()-1 && nums[left]==left) return nums.size();
else return nums[left]-1;
}
- 注意:最后记得考虑查找的元素是不是一定就在一开始划定的搜索区间中
3. 附录
- 题目:0~n-1中缺失的数字