【LeetCode】81. Search in Rotated Sorted Array II(C++)
阿新 • • 發佈:2018-12-19
地址:https://leetcode.com/problems/search-in-rotated-sorted-array-ii/
題目:
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., [0,0,1,2,2,5,6]
might become [2,5,6,0,0,1,2]
).
You are given a target value to search. If found in the array return true
, otherwise return false
Example 1:
Input: nums = [2,5,6,0,0,1,2], target = 0
Output: true
Example 2:
Input: nums = [2,5,6,0,0,1,2], target = 3
Output: false
Follow up:
- This is a follow up problem to Search in Rotated Sorted Array, where nums may contain duplicates.
- Would this affect the run-time complexity? How and why?
理解:
這個題和Search in Rotated Sorted Array的區別是這裡給出的陣列中有重複值。會導致邊界條件不太一樣。
在上一題中,如果nums[mid]>nums[hi]
,就說明右邊是先升後降,否則左邊是先升後降。然後需要判斷應該取左邊的區間還是右邊的區間。
實現:
因為本題中有重複,因此在一開始處理了一下重複元素。處理了之後,mid應該是不會和left還有right相等的,然後再判斷
- num[mid]>nums[hi],因此右半段是先升後降
- 否則,num[mid]<num[lo],左半段是先升後降
- 否則, 從l到h是有序的,使用普通的二分查詢
class Solution {
public:
bool search(vector<int>& nums, int target) {
int lo = 0, hi = nums.size() - 1;
while (lo <= hi) {
while (lo < hi&&nums[lo + 1] == nums[lo]) ++lo;
while (lo < hi&&nums[hi - 1] == nums[hi]) --hi;
int mid = lo + ((hi - lo) >> 1);
if (nums[mid] == target) return true;
if (nums[mid] > nums[hi]) {
if (target < nums[mid] && target >= nums[lo]) hi = mid - 1;
else lo = mid + 1;
}
else if (nums[mid] < nums[lo])
if (target > nums[mid] && target <= nums[hi]) lo = mid + 1;
else hi = mid - 1;
else
if (target > nums[mid]) lo = mid + 1;
else hi = mid - 1;
}
return false;
}
};
或者修改下上一題的解法,在[1, 3, 1, 1, 1]
這種形式的陣列中,因為nums[lo]
、nums[mid]
以及nums[hi]
相等,導致無法根據端點判斷。可以先把這種情況跳過,如下:
class Solution {
public:
int search(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (nums[mid] == target) return true;
if (nums[l] == nums[mid] && nums[r] == nums[mid]) {
++l;
--r;
}
else if (nums[mid] > nums[r]) {
if (target > nums[mid] || target <= nums[r]) l = mid + 1; // condition for pick right side
else r = mid - 1; // else, pick left side
}
else {
if (target <= nums[r] && target > nums[mid]) l = mid + 1; // condition for pick right side
else r = mid - 1; // else, pick left side
}
}
return false;
}
};