[附錄了其他兩個人的代碼,給出了鏈接]
題目
Given a sorted array of integers, find the starting and ending position of a given target value.
Your algorithm’s runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1].
For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4]
自己的想法
很明確要二分查找(O(log n)),對於一個區間 [left, right]:
1.如果 target 不在其中 [left] > target or [right] < target,則返回 [-1, -1];
2.看中點(mid = (left+right)/2)與 target 的大小
2.1.如果 [mid] > target,說明在區間 [left, mid];
2.2.如果 [mid] < target,說明在區間 [mid + 1, right];
2.3.否則,[mid] == target,說明 mid 是在結果中,我們在分別考慮左右兩側,得到
[left1, right1] 與 [left2, right2].然後拼接整理結果:
2.3.1.如果 left1 == -1,則返回 [left2, right2]
2.3.2.如果 left2 == -1,則返回 [left1, right1] (其實肯定是 [-1, -1])
2.3.2.返回 [left1, right2] (即兩者都在結果之中,拼接返回即可)
python 代碼 [自己對邊界的處理還是不好,需要注意]
class Solution(object):
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
return self.searchLR(nums, target, 0, len(nums) - 1)
def searchLR(self, nums, target, left, right):
if nums[left] > target or nums[right] < target:
return [-1, -1]
if left == right: # left==right should take care
if nums[left] == target:
return [left, left]
else:
return [-1, -1]
mid = (left + right)//2
if nums[mid] < target: #[mid] 較小,應在 mid 右側
return self.searchLR(nums, target, mid + 1, right)
elif nums[mid] > target:
return self.searchLR(nums, target, left, mid)
else: #相等,說明在其兩端
[l1, r1] = self.searchLR(nums, target, left, mid)
[l2, r2] = self.searchLR(nums, target, mid + 1, right)
if l1 == -1:
return [l2, r2]
if l2 == -1:
return [l1, r1]
#即兩端都有
return [l1, r2]
網上看到更優雅些的
其實題目只需二分查找值爲 target 最左與最右邊的位置即可。
個人感覺很厲害的一個人寫的
他在處理 [mid] == key 時對 pos 的再次賦值做的很好(pos == -1 ? mid : pos),如果在左邊(或右邊,取決於尋找最左還是最右)沒能找到值爲 key 的位置,直接將 mid 返回。
class Solution {
public:
int findPos(int a[], int beg, int end, int key, bool findLeft)
{
if (beg > end)
return -1;
int mid = (beg + end) / 2;
if (a[mid] == key)
{
int pos = findLeft ? findPos(a, beg, mid - 1, key, findLeft) : findPos(a, mid + 1, end, key, findLeft);
return pos == -1 ? mid : pos;
}
else if (a[mid] < key)
return findPos(a, mid + 1, end, key, findLeft);
else
return findPos(a, beg, mid - 1, key, findLeft);
}
vector<int> searchRange(int A[], int n, int target) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int leftPos = findPos(A, 0, n - 1, target, true);
int rightPos = findPos(A, 0, n - 1, target, false);
vector<int> ret;
ret.push_back(leftPos);
ret.push_back(rightPos);
return ret;
}
};
另一個“抽象”點的
因爲他的 binarySearch 在 [mid] <= target 時更新了一下返回值,這樣在 [mid + 1, right] 沒能找到時可以直接返回 mid。
class Solution {
public:
vector<int> searchRange(int A[], int n, int target) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
vector<int> res(2);
res[0] = binarySearch(A, n, target - 1) + 1;
res[1] = binarySearch(A, n , target);
if(res[1] == -1 || A[res[1]] != target){
res[0] = -1;
res[1] = -1;
}
return res;
}
int binarySearch(int A[], int n, int target){
int l = 0;
int r = n -1;
int m = (l+r)/2;
int ret = -1;
while(l<=r){
if(A[m] > target){
r = m - 1;
m = (l+r)/2;
}
else{
ret = m;
l = m + 1;
m = (l+r)/2;
}
}
return ret;
}
};