1. 程式人生 > >【LeetCode】81. Search in Rotated Sorted Array II(C++)

【LeetCode】81. Search in Rotated Sorted Array II(C++)

地址: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相等的,然後再判斷

  1. num[mid]>nums[hi],因此右半段是先升後降
  2. 否則,num[mid]<num[lo],左半段是先升後降
  3. 否則, 從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;
	}
};