【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;
	}
};

猜你喜欢

转载自blog.csdn.net/Ethan95/article/details/84919297