這道題屬于是二分查找的入門題了,我依稀記得一些二分查找的編碼要點,但是最后還是寫出了一個死循環,無語(ˉ▽ˉ;)…又回去看了下自己當時的博客和卡哥的視頻,這才發現自己分情況只分了兩種,最后導致死循環。。。下面直接說思路。本題我們采用左閉右開的二分查找法,左區間的搜索范圍為[left, mid)
,而右區間的搜索范圍為[mid, right)
,我們要確保這兩個查找區間在初始狀態下覆蓋整個數組的元素,因此left
初始化為0
,right
初始化為nums.size()
,而不是nums.size() - 1
,下面來討論區間的更新情況:
- 當
nums[mid] > target
時,則右區間內所有的元素都比target
大,插入位置應當在左區間內,因此我們將right
賦值為mid
(因為nums[mid] > target
,所以原來的nums[mid]
不應包含在區間內,right
賦值為mid
而不是mid - 1
) - 當
nums[mid] < target
時,則左區間內所有元素都比target
小,插入位置應當在右區間內,因此我們將left
賦值為mid
(因為nums[mid] < target
,新的區間不應當繼續包含nums[mid]
,left
賦值為mid + 1
而不是mid
) - 當
nums[mid] == target
時,說明我們在數組中找到了與target
值一樣的元素,根據輸入樣例,我們直接將元素插入當前位置,原來的元素后移一位即可,所以我們直接返回mid
。
循環條件是查找區間合法,對于左開右閉的區間,我們必須要保證里面至少有一個元素,因此left
不能等于right
,必須要保證left < right
,左閉右開的區間才是合法的。
當循環正常結束,一定是數組中沒有與target
相等的元素,最終觸發left == right
,退出循環,此時left
和right
返回哪個都可以,此時nums[left]
對應的是數組中第一個大于target
的元素,在此處插入,則該位置及以后的元素向后移一位,依然能保證插入后有序。
class Solution {
public:int searchInsert(vector<int>& nums, int target) {int left = 0, right = nums.size();int mid;//使用左閉右開的找法//左邊的查找范圍為[left, mid),右邊的查找范圍為[mid, right)//對于左閉右開的區間,左右端點的差值至少為1才合法while(left < right){mid = (left + right) / 2;if(nums[mid] > target) //插入位置在左區間內right = mid;else if(nums[mid] < target)left = mid + 1;else return mid; }return left;}
};