這道題考察二分法的細(xì)節(jié)忙芒。
其實(shí)如果不是對(duì)二分法很熟凰棉,挺容易出小錯(cuò)誤的膀哲,寫(xiě)不干凈往产。
主要考察二分法的邊界條件,退出規(guī)則某宪。
首先 先找First position.
當(dāng)中間的數(shù)大于等于target時(shí)仿村,把右邊界移到m.
否則把左邊界移到m + 1;
退出條件是只剩一個(gè)數(shù)。如果這個(gè)數(shù)是target, 則把l這個(gè)位置記下來(lái)兴喂,否則記 -1蔼囊;
然后找last position.
當(dāng)中間的數(shù)小于等于target時(shí),把左邊界移到m
否則把右邊界移到m - 1;
但是你看代碼里面衣迷,求m的方式在兩個(gè)while loop里是略不一樣的畏鼓。
一個(gè)是 int m = l + (r - l) / 2;
一個(gè)是 int m = r - (r - l) / 2;
這兩句話的區(qū)別是在只剩兩個(gè)數(shù)的時(shí)候,第一個(gè)取左邊那個(gè)蘑险,第二個(gè)是取的右邊那個(gè)滴肿。
對(duì)于第一個(gè)循環(huán),當(dāng)只剩兩個(gè)數(shù)a, b的時(shí)候佃迄,取了左邊的那一個(gè)數(shù)a作為m泼差,然后下一步是要么r = m , 要么l = m + 1, 都是只剩了一個(gè)數(shù)。這時(shí)如果取右邊的那個(gè)數(shù)的話呵俏,r就stuck在m上了堆缘,無(wú)法退出循環(huán)。
對(duì)第二個(gè)循環(huán)普碎,當(dāng)只剩兩個(gè)數(shù)a, b時(shí)吼肥,取了右邊的那個(gè)數(shù)b作為m. 下一步要么是 l =m 要么是r = m - 1, 也是只剩下了一個(gè)數(shù),可以退出循環(huán)。這時(shí)如果和第一個(gè)循環(huán)一樣取左邊的那個(gè)數(shù)a缀皱,l就stuck在了a (就是m)上了斗这。
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> ans{-1, -1};
if (nums.size() < 1) return ans;
int l = 0, r = nums.size() - 1;
while (l < r) {
int m = l + (r - l) / 2;
if (nums[m] >= target) r = m;
else l = m + 1;
}
if (nums[l] == target) ans[0] = l;
else return ans;
l = 0;
r = nums.size() - 1;
while (l < r) {
int m = r - (r - l) / 2;
if (nums[m] <= target) l = m;
else r = m - 1;
}
if (nums[l] == target) ans[1] = r;
return ans;
}
};
其實(shí)這個(gè)判斷條件還可以寫(xiě)的更細(xì)一點(diǎn)璧微,分三種
如果 nums[m] =, >, < 各寫(xiě)一個(gè)殖侵。但其實(shí)沒(méi)多少必要夫啊。
我也寫(xiě)了一個(gè)這種情況下的code灭衷,帖在下面。
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> ans{-1, -1};
if (nums.size() < 1) return ans;
int l = 0, r = nums.size() - 1;
while (l < r) {
int m = l + (r - l) / 2;
if (nums[m] == target) r = m;
else if (nums[m] < target) l = m + 1;
else r = m - 1;
}
if (nums[l] == target) ans[0] = l;
else return ans;
l = 0;
r = nums.size() - 1;
while (l < r) {
int m = r - (r - l) / 2;
if (nums[m] == target) l = m;
else if (nums[m] < target) l = m + 1;
else r = m - 1;
}
if (nums[r] == target) ans[1] = r;
return ans;
}
};