【LeetCode】34. Find First and Last Position of Element in Sorted Array(C++)
地址:https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/
題目:
Given an array of integers nums
sorted in ascending order, find the starting and ending position of a given target value.
Your algorithm’s runtime complexity must be in the order of .
If the target is not found in the array, return .
Example 1:
Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]
Example 2:
Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]
理解:
一直覺得二分查詢坑實在是太多,查詢小於的,查詢大於的,查詢第一個等於的,最後一個等於的。。。
這個題就是要查詢第一個等於的和最後一個等於的。
實現:
二分查詢mid=(l+h)/2因為截斷總會得到靠左的元素。
如果在迴圈中要令l=mid或者h=mid,判斷條件就應該是while(l<h),否則可能會一直迴圈下去。
對於findLeft
,h最後指向的是大於等於target的第一個元素。跳出迴圈的時候,l==h
,只需要判斷這個元素是不是等於target即可。
對於findRight
,本來想和上面一樣用對稱的思路,但是由於截斷,導致會陷入死迴圈,因此改了一下思路。
在最後一次迴圈內,l==h==mid
,如果這個元素小於等於target,會把l改變,否則會減小h。即這種情況下,h總會指向最後一個等於target的元素。
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if (nums.empty()) return{ -1,-1 };
int l = findLeft(nums, target);
if (l == -1) {
return{ -1,-1 };
}
return{ l,findRight(nums,target) };
}
private:
int findLeft(vector<int>& nums, int target) {
int l = 0, h = nums.size()-1;
while (l < h) {
int mid = l + (h - l) / 2;
// shrink the range such that h point to the left-most num that >= target
if (nums[mid] >= target)
h = mid;
// nums[mid]<target, then l should be bigger than mid, let l=mid+1
else
l = mid + 1;
}
// since h point to the left-most num that >= target, finally l=h.
// if nums[l]==target,return the index, otherwise, return -1
return nums[l]==target?l:-1;
}
int findRight(vector<int>& nums, int target) {
int l = 0, h = nums.size() - 1;
while (l <= h) {
int mid = l + (h - l) / 2;
if (nums[mid] <= target)
l = mid + 1;
else
h = mid - 1;
}
return nums[h] == target ? h : -1;
}
};
更一下:
關於截斷導致不能用對稱的方法做的,解決方法的確是在計算mid的時候手動加1從而指向靠右的位置。詳見Clean iterative solution with two binary searches (with explanation)