LeetCode35题 理一下二分法的思路——为什么返回left
35. 搜索插入位置
题目描述:
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素
代码
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
int mid = 0;
while(left <= right){
mid = (left + right) / 2;
if(nums[mid] == target){
return mid;
}else if(nums[mid] < target){
left = mid + 1;
}else {
right = mid - 1;
}
}
return left;
}
}
疑惑与解释
我很自然的写出上述的代码,但是深究其中原理倒是一知半解,所以特地好好地思索了一会。我主要的问题有以下两个:
1.为什么返回left,而且right不行?
答:考虑查找不成功的情况,即最后一次即left==right
的时候,
如果是nums[mid] < target
,那么target应该插入到当前结点的下一个,即最后应该插入到left+1
的位置。我们看代码,一开始mid == left == right
,然后执行了left = mid + 1;
,那么退出循环时,left就是待插入的位置了;
如果是nums[mid] > target
,那么target应该插入到当前结点left
的前面,那么插入后的位置就是当前位置left
,后面的操作并没有修改left,所以待插入位置就是left
2.为什么直接返回mid不行?
答:同上理,最后一次的时候,mid记录的是执行if语句之前的left值,执行if语句之后返回的值left可能会改变,所以为了与上述一致,那么需要另一个变量ans来保存left修改后的值,即类似官方题解的做法:
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
int ans = 0;//保存最后的返回值
while(left <= right){
int mid = (left + right) / 2;
if(nums[mid] == target){
ans = mid;
break;
}else if(nums[mid] < target){
ans = left = mid + 1;
}else {
right = mid - 1;
}
}
return ans;
}
}