[附录了其他两个人的代码,给出了链接]
题目
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;
}
};