Search in Rotated Sorted Array II

medium

You are given an integer array nums that was originally sorted in non-decreasing order — but it may contain duplicate values. Before it reaches you, the array is rotated at some unknown pivot index k (0 <= k < nums.length), so it becomes [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]].

For example, [0,1,2,4,4,4,5,6,6,7] rotated at pivot index 5 becomes [4,5,6,6,7,0,1,2,4,4].

Given the rotated array nums and an integer target, return true if target exists in nums, and false otherwise.

A plain linear scan works — but the interviewer wants you to decrease the overall number of operation steps as much as possible. Can you exploit the leftover sorted structure, and can you explain exactly where duplicates hurt you?

Hints

If the array had no duplicates, one comparison between nums[lo] and nums[mid] would tell you which half is sorted. What could go wrong with that comparison here?
When nums[lo], nums[mid], and nums[hi] are all equal, the comparison carries no information — the target could hide in either half. You cannot discard half the array.
In that all-equal case, you have already checked nums[mid] against the target — so nums[lo] and nums[hi] cannot be the target either. Shrink both ends by one and retry; otherwise binary-search the sorted half exactly like the classic rotated-array search.

Common doubts

Consider an array of 4999 copies of 1 hiding a single 2, with target = 2. Every probe sees nums[lo] == nums[mid] == nums[hi], so each step can only shrink the range by two — and no algorithm can do better, because the 2 could be at any unexamined position. Duplicates destroy the guarantee, not just this particular algorithm.
With duplicates, target may appear many times, so which index to return is ambiguous. Existence is the natural question. (Returning the first occurrence is a good follow-up — it combines this technique with a lower-bound search.)
No. The shrink only fires after nums[mid] != target is confirmed, and it only fires when nums[lo] and nums[hi] equal nums[mid]. Values already ruled out as the target are always safe to drop.
Yes. A pivot of 0 reproduces the sorted array, in which case nums[lo] <= nums[mid] always holds and the algorithm behaves as plain binary search on the left-sorted branch.

Interview follow-ups

First locate the pivot (minimum) with a duplicate-tolerant binary search, then run a lower-bound binary search on the logical sorted order using index arithmetic modulo n — or simpler, binary-search each of the two sorted segments for the leftmost occurrence. Same O(log n) average, O(n) worst.
The same tie-breaking idea: compare nums[mid] with nums[hi]; when they are equal you cannot tell which side holds the minimum, so decrement hi by one. That is exactly Find Minimum in Rotated Sorted Array II.
No. An adversary argument settles it: in an array of identical values with at most one different element, any unexamined position could hold the target, so every comparison-based algorithm must inspect Ω(n) elements in the worst case.

Fun facts

  • The one-line difference from the duplicate-free version — shrink both ends on a three-way tie — is enough to change the provable worst case from O(log n) to O(n). Few problems show so crisply how a small change in input guarantees reshapes complexity.
  • The safe-to-shrink argument (equal values already ruled out cannot be the answer) is the same trick that powers Find Minimum in Rotated Sorted Array II and several duplicate-tolerant two-pointer problems.
  • Interviewers love the follow-up question about complexity here: stating 'O(log n) average, O(n) worst — and here is the adversarial input' before being asked is a strong senior signal.

Asked at

AmazonMicrosoftGoogleBloombergAdobe
Frequently Sometimes Occasionally
Example 1
Input: nums = [2,5,6,0,0,1,2], target = 0
Output: true
The sorted array [0,0,1,2,2,5,6] was rotated to [2,5,6,0,0,1,2]; 0 appears in it.
Example 2
Input: nums = [2,5,6,0,0,1,2], target = 3
Output: false
3 does not appear anywhere in the array.
Constraints

- 1 <= nums.length <= 5000 - -10^4 <= nums[i] <= 10^4 - nums is guaranteed to be rotated at some pivot (possibly pivot 0, leaving it fully sorted) - -10^4 <= target <= 10^4

Solve this problem →