Search in Rotated Sorted Array

Medium Binary Search

Problem

Given an integer array nums sorted in ascending order and rotated at an unknown pivot, and an integer target, return the index of target if it is in nums, or -1 if it is not in nums.

  • 1 ≤ nums.length ≤ 5000
  • −10⁴ ≤ nums[i] ≤ 10⁴
  • All values of nums are unique.
  • nums is guaranteed to be rotated at some pivot.
  • −10⁴ ≤ target ≤ 10⁴

Example

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

The array is rotated at pivot index 3. The algorithm uses a modified binary search to identify which half of the array is sorted at each step. Initially, the left half [4,5,6,7] is sorted. Since target 0 is not in this range, the search moves to the right half [0,1,2]. The process repeats until the target is found at index 4.

Approach

Straightforward Solution

A naive approach is to perform a linear scan, which is O(n) and inefficient for large arrays. A standard binary search fails because the array is not fully sorted.

Core Observation

A rotated sorted array consists of two sorted subarrays. At any point, one half of the current search interval is sorted. This property allows binary search to be adapted by determining which half is sorted and whether the target lies within it.

Path to Optimal

The key recognition signals are 'rotated sorted array' and 'search in O(log n)'. These indicate a Modified Binary Search because the array is partially sorted in two segments. By checking the relative order of nums[l], nums[mid], and nums[r], the algorithm identifies the sorted half and decides which half to discard, maintaining logarithmic time complexity.

Optimal Approach

Use a binary search with pointers l and r. At each iteration, compute mid. If nums[mid] equals target, return mid. Otherwise, check if the left half is sorted (nums[l] <= nums[mid]). If yes, determine if target lies within [nums[l], nums[mid]] to decide which half to search next. If the left half is not sorted, the right half must be sorted, and a similar check is performed. This approach discards half the search space each iteration, guaranteeing O(log n) time.

Time

O(log n)

Each iteration halves the search space by discarding one sorted half, leading to logarithmic time complexity.

Space

O(1)

Only a fixed number of variables (pointers and indices) are used, with no additional data structures.

Pattern Spotlight

Modified Binary Search (Rotated Sorted Array)

At each step, identify which half of the array is sorted, then decide if the target lies within that half; discard the other half to maintain O(log n) search despite rotation.

Solution

1class Solution:
2 def search(self, nums: list[int], target: int) -> int:
3 l, r = 0, len(nums) - 1
4
5 while l <= r:
6 mid = (l + r) // 2
7 if nums[mid] == target:
8 return mid
9
10 if nums[l] <= nums[mid]:
11 if target > nums[mid] or target < nums[l]:
12 l = mid + 1
13 else:
14 r = mid - 1
15 else:
16 if target < nums[mid] or target > nums[r]:
17 r = mid - 1
18 else:
19 l = mid + 1
20
21 return -1

Step-by-Step Solution

1

Initialize Search Boundaries for Binary Search

3l, r = 0, len(nums) - 1

Objective

To set the initial left and right pointers to cover the entire array for binary search.

Key Insight

Starting with l at 0 and r at the last index ensures the entire array is considered. This setup is essential for the binary search to progressively narrow down the search space.

Interview Quick-Check

Core Logic

Initialize pointers to the full array range to begin the binary search.

State & Boundaries

Pointers l and r define the current search interval, which shrinks each iteration.

2

Perform Modified Binary Search Loop to Locate Target

5while l <= r:
6 mid = (l + r) // 2
7 if nums[mid] == target:
8 return mid
10 if nums[l] <= nums[mid]:
11 if target > nums[mid] or target < nums[l]:
12 l = mid + 1
13 else:
14 r = mid - 1
15 else:
16 if target < nums[mid] or target > nums[r]:
17 r = mid - 1
18 else:
19 l = mid + 1

Objective

To iteratively narrow the search space by identifying the sorted half and deciding which half to explore next.

Key Insight

The algorithm leverages the property that one half of the array is sorted. By comparing nums[l], nums[mid], and nums[r], it determines which half is sorted and whether the target lies within that half. This logic allows discarding the other half safely, maintaining O(log n) complexity despite rotation.

Interview Quick-Check

Core Logic

At each iteration, check if nums[mid] is the target; if not, determine which half is sorted and whether the target lies within it to decide the next search boundaries.

State & Boundaries

The loop continues while l <= r, ensuring all possible indices are considered.

Common Pitfalls & Bugs

Incorrectly handling the comparison operators or boundary conditions can cause infinite loops or missed targets.

3

Return -1 When Target is Not Found

21return -1

Objective

To indicate the target does not exist in the array after exhausting the search space.

Key Insight

Returning -1 after the loop terminates confirms that the target was not found. This is the standard sentinel value for unsuccessful searches.

Interview Quick-Check

Core Logic

Return -1 to signal the absence of the target in the array.

Line Analysis

This solution has 5 Critical lines interviewers watch for.

Line 7 Critical
if nums[mid] == target:

Check whether the midpoint value equals the target.

An exact midpoint match solves the search immediately.

Line 8 Critical
return mid

Return the midpoint index.

Returning immediately avoids unnecessary further work once the target is found.

Line 10 Critical
if nums[l] <= nums[mid]:

Check whether the left half is sorted.

At each step, one half must be sorted; this condition identifies the sorted left half.

Line 15 Critical
else:

Enter the branch where the right half is sorted.

If the left half is not sorted, then the right half must be sorted.

Line 21 Critical
return -1

Return -1 when the target is absent.

If the interval is exhausted without a match, the target is not present.

Line 6 Core
mid = (l + r) // 2

Compute the midpoint index.

The midpoint splits the rotated array interval for the modified binary search decision.

Line 11 Core
if target > nums[mid] or target < nums[l]:

Determine whether the target is outside the sorted left half.

If the target lies outside the sorted left-half range, the search must continue on the right.

Line 12 Core
l = mid + 1

Move the left pointer to the right half.

Discarding the sorted left half is safe when the target cannot lie inside it.

Line 13 Core
else:

Enter the branch that keeps searching the left half.

Reaching this branch means the target must lie inside the sorted left half.

Line 14 Core
r = mid - 1

Move the right pointer to the left half.

Moving the right pointer left keeps only the part of the sorted left half that can still contain the target.

Line 16 Core
if target < nums[mid] or target > nums[r]:

Determine whether the target is outside the sorted right half.

If the target lies outside the sorted right-half range, the search must move left.

Line 17 Core
r = mid - 1

Move the right pointer to the left half.

Discarding the sorted right half is safe when the target cannot lie inside it.

Line 18 Core
else:

Enter the branch that keeps searching the right half.

Reaching this branch means the target must lie inside the sorted right half.

Line 19 Core
l = mid + 1

Move the left pointer to the right half.

Moving the left pointer right keeps only the part of the sorted right half that can still contain the target.

Line 3 Core
l, r = 0, len(nums) - 1

Initialize the left and right pointers.

Initializing the search boundaries to the full array ensures every index is initially considered.

Line 5 Core
while l <= r:

Binary search while the interval is valid.

The loop continues while the current search interval still contains candidates.

Test Your Understanding

Why does checking which half is sorted allow the algorithm to discard half the search space correctly?

Because in a rotated sorted array, one half is always sorted. If the target lies outside the sorted half's range, it must be in the other half, allowing safe discarding of the sorted half and preserving correctness.

Related Problems

Binary Search pattern

Don't just read it. Drill it.

Reconstruct Search in Rotated Sorted Array from memory until it sticks. AlgoDrill blanks out key lines and makes you fill them back in, step by step.

Unlock the Search in Rotated Sorted Array drill

or drill a free problem