Find a Value in a Rotated Sorted Array That May Contain Duplicates
Solve this Problemnums may now contain duplicate values. Given the rotated array nums and an integer target, return true if target is present, or false otherwise.
Duplicates mean nums[lo], nums[mid], and nums[hi] can all tie, making it impossible to tell which half is sorted — when that happens, shrink both ends inward by one and try again. This pushes the worst case to O(n), but the algorithm still behaves like binary search whenever the tie doesn't occur.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ nums.length ≤ 5000 - ◆
-10⁴ ≤ nums[i] ≤ 10⁴ - ◆
nums was sorted in non-decreasing order, then rotated at some unknown pivot - ◆
nums may contain duplicate values - ◆
-10⁴ ≤ target ≤ 10⁴
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
| 1 | class Solution { |
| 2 | public boolean searchRotatedWithDuplicates(int[] nums, int target) { |
| 3 | int lo = 0, hi = nums.length - 1; |
| 4 | while (lo <= hi) { |
| 5 | int mid = lo + (hi - lo) / 2; |
| 6 | if (nums[mid] == target) return true; |
| 7 | if (nums[lo] == nums[mid] && nums[mid] == nums[hi]) { |
| 8 | lo++; |
| 9 | hi--; |
| 10 | } else if (nums[lo] <= nums[mid]) { |
| 11 | if (nums[lo] <= target && target < nums[mid]) { |
| 12 | hi = mid - 1; |
| 13 | } else { |
| 14 | lo = mid + 1; |
| 15 | } |
| 16 | } else { |
| 17 | if (nums[mid] < target && target <= nums[hi]) { |
| 18 | lo = mid + 1; |
| 19 | } else { |
| 20 | hi = mid - 1; |
| 21 | } |
| 22 | } |
| 23 | } |
| 24 | return false; |
| 25 | } |
| 26 | } |
| 27 |
06Search the full range [0, 6] for target 1. Unlike the duplicate-free version, nums[lo] and nums[mid] can now tie even when we can't tell which half is sorted.
Approach & Solutions
Brute Force — Linear Scan
BruteDuplicates or not, a plain left-to-right scan always works — check every value against target. It's correct on any input, but it gives up the O(log n) speed that binary search would normally offer on a (mostly) sorted array.
O(n)O(1)1class Solution {
2 public boolean searchRotatedWithDuplicates(int[] nums, int target) {
3 for (int i = 0; i < nums.length; i++) {
4 if (nums[i] == target) return true;
5 }
6 return false;
7 }
8}Optimal — Modified Binary Search with Duplicate Handling
OptimalSame idea as the duplicate-free version — figure out which half is sorted and search there if target fits its range — except duplicates can make nums[lo], nums[mid], and nums[hi] all equal, which hides which half is actually sorted. When that happens, there's no shortcut: shrink lo and hi inward by one and try again. That fallback is what pushes the worst case to O(n).
O(log n) average, O(n) worst caseO(1)1class Solution {
2 public boolean searchRotatedWithDuplicates(int[] nums, int target) {
3 int lo = 0, hi = nums.length - 1;
4 while (lo <= hi) {
5 int mid = lo + (hi - lo) / 2;
6 if (nums[mid] == target) return true;
7 if (nums[lo] == nums[mid] && nums[mid] == nums[hi]) {
8 lo++;
9 hi--;
10 } else if (nums[lo] <= nums[mid]) {
11 if (nums[lo] <= target && target < nums[mid]) {
12 hi = mid - 1;
13 } else {
14 lo = mid + 1;
15 }
16 } else {
17 if (nums[mid] < target && target <= nums[hi]) {
18 lo = mid + 1;
19 } else {
20 hi = mid - 1;
21 }
22 }
23 }
24 return false;
25 }
26}