题目:
思路:
按照二分查找的思路来,然后调用vector的insert就可以。
代码:
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
int middle = (left + right) / 2;
while (left <= right) {
if (nums[middle] == target) {
return middle;
}
else if (nums[middle] < target) {
left = middle + 1;
middle = (left + right) / 2;
}
else {
right = middle - 1;
middle = (left + right) / 2;
}
}
nums.insert(nums.begin() + middle, target);
return right+1;
}
};
Debug:
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
int middle = (left + right) / 2;
// 二分查找
while (left <= right) {
if (nums[middle] == target) {
// 返回找到target的位置
return middle;
}
else if (nums[middle] < target) {
left = middle + 1;
middle = (left + right) / 2;
}
else {
right = middle - 1;
middle = (left + right) / 2;
}
}
// 没找到,就在合适的位置insert
nums.insert(nums.begin() + middle, target);
// 返回插入的位置
return middle;
}
};
第一次提交的代码指通过了39/62个测试用例,如下图
从该测试用例来看,程序执行过程如下:
-
left = 0, right = 3, middle = 1, val = 2
-
nums[middle] = 3 > val
-
right = middle -1 = 0, left = 0, middle = 0
-
nums[middle] = 1 < val
-
left = middle +1 = 1, right = 0, middle = 0, left > right
跳出循环 -
本代码插入的位置是0,正确答案应该是1。
经过分析,如果最后跳出循环,那么必然是因为
left > right
,反推一下,在循环中发生了left = middle + 1
或者right = middle - 1
。 -
left = middle + 1
:说明nums[middle] < target
,那么要插入的位置就是当前middle + 1
。但是因为会执行第15行的middle = (left + right) / 2
,所以需要插入的是middle+1
或right+1
位置。 -
right = middle - 1
:说明nums[middle] > target
,那么要插入的位置就是当前middle - 1
。因为middle = (left + right)/2
仍要执行,所以需要插入的是middle+1
或right+1
位置。第二次提交,尝试
return middle+1
,出现以下错误。
经过分析,发现以上讨论漏了一种情况——目标值插入在所有元素之前,right < 0, left = 0, middle = (left + right)/2 = 0
,如果用middle+1
,就会插入在1
的位置,所以我们选择return right+1
,提交代码,解答正确。