給定一個升序無重複數組 nums 和目標值 target,若目標值存在返回其下標;否則返回其應插入的位置以保持數組有序。例如:
[1,3,5,6], 5 → 2;[1,3,5,6], 2 → 1;[1,3,5,6], 7 → 4;[1,3,5,6], 0 → 0。
維護左閉右閉區間 [left, right],每輪取中間索引 mid = left + (right - left) / 2:
nums[mid] == target,直接返回 midnums[mid] < target,目標在右半區,left = mid + 1nums[mid] > target,目標在左半區,right = mid - 1循環結束時 left > right,此時 left 即為插入位置。因為:
< target 的元素在 left 左側> target 的元素在 right 右側left == right + 1,空位正好在 leftclass Solution {
public:
int searchInsert(vector& nums, int target) {
int left = 0, right = (int)nums.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) return mid;
else if (nums[mid] < target) left = mid + 1;
else right = mid - 1;
}
return left; // 未找到時 left 即插入位置
}
};
使用 mid = left + (right - left) / 2 而非 (left + right) / 2,防止 left + right 超過 INT_MAX。
本解法採用 左閉右閉 [left, right],循環條件 left <= right,更新邊界時 +1/-1。若改用左閉右開 [left, right),則循環條件為 left < right,更新 left = mid + 1 / right = mid,返回 left 同理。
原文採用 if (A[m] > target) return m; else return m + 1; 判斷插入位置,但循環結束時 m 為最後一次計算的中間值,未必等於 left,可能導致邊界錯誤。標準寫法直接返回 left 更穩健。
搜索插入位置是二分查找的經典應用,關鍵在於理解循環終止時 left 的語義:它始終指向第一個 ≥ target 的位置,正是插入點。掌握左閉右閉/左閉右開兩種區間寫法並能相互轉換,是二分查找進階的基礎。