Find Minimum in Rotated Sorted Array

Medium Binary Search

Problem

Given an array nums that is sorted in ascending order and is rotated at an unknown pivot, return the minimum element in nums. You may assume no duplicate exists in the array.

  • 1 ≤ nums.length ≤ 5000
  • −5000 ≤ nums[i] ≤ 5000
  • All integers of nums are unique
  • nums is sorted and rotated between 1 and nums.length times

Example

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

A brute-force approach would scan the entire array to find the minimum, which is inefficient for large inputs. The optimal approach uses a modified binary search to exploit the rotated sorted property. Starting with pointers at the array's ends, the algorithm compares values to determine which half contains the minimum. For example, at the first iteration, the algorithm compares nums[l]=4 and nums[r]=2. Since nums[l] > nums[r], the minimum must be in the right half. It calculates the middle index m=3, nums[m]=7, updates the result to min(4,7)=4, and moves the left pointer to m+1=4. The process repeats until the minimum is found at index 4 with value 0.

Approach

Straightforward Solution

A linear scan through the array to find the minimum element, which takes O(n) time and is inefficient for large arrays.

Core Observation

The rotated sorted array consists of two sorted subarrays. The minimum element is the only element where the previous element is greater, or it is the smallest element in the array. The key property is that if nums[l] < nums[r], the subarray is already sorted, and nums[l] is the minimum.

Path to Optimal

The key recognition signals are 'rotated sorted array' and 'find minimum' which indicate a modified binary search. The algorithm exploits the fact that one half of the array is always sorted. By comparing nums[l], nums[m], and nums[r], it determines which half contains the minimum and discards the other half, reducing the search space by half each iteration.

Optimal Approach

Use a binary search with pointers l and r. If nums[l] < nums[r], the subarray is sorted and nums[l] is the minimum. Otherwise, calculate mid m, update the result with nums[m], and decide which half to search next based on the comparison between nums[m] and nums[l]. This approach guarantees O(log n) time complexity.

Time

O(log n)

Each iteration halves the search space by discarding one half of the array based on comparisons, leading to logarithmic time complexity.

Space

O(1)

Only a fixed number of variables (pointers and result) are used, requiring constant auxiliary space.

Pattern Spotlight

Modified Binary Search (Rotated Sorted Array)

When searching in a rotated sorted array, use the property that one half is always sorted to discard half the search space by comparing boundary and middle elements, enabling O(log n) search for the minimum.

Solution

1class Solution:
2 def findMin(self, nums: list[int]) -> int:
3 res = nums[0]
4 l, r = 0, len(nums) - 1
5
6 while l <= r:
7 if nums[l] < nums[r]:
8 res = min(res, nums[l])
9 break
10
11 m = (l + r) // 2
12 res = min(res, nums[m])
13 if nums[m] >= nums[l]:
14 l = m + 1
15 else:
16 r = m - 1
17
18 return res

Step-by-Step Solution

1

Initialize Result and Search Boundaries

3res = nums[0]
4l, r = 0, len(nums) - 1

Objective

To set up the initial minimum candidate and pointers for the binary search over the rotated array.

Key Insight

Starting with res as nums[0] ensures the algorithm always has a baseline minimum to compare against. Initializing pointers l and r at the array boundaries sets the stage for a binary search that progressively narrows the search space to find the minimum element.

Interview Quick-Check

Core Logic

Initialize res with nums[0] to track the minimum found so far during the binary search.

State & Boundaries

Set l and r to the start and end indices of the array to cover the entire search space initially.

2

Iteratively Narrow Search Space Using Modified Binary Search

6while l <= r:
7 if nums[l] < nums[r]:
8 res = min(res, nums[l])
9 break
11 m = (l + r) // 2
12 res = min(res, nums[m])
13 if nums[m] >= nums[l]:
14 l = m + 1
15 else:
16 r = m - 1

Objective

To repeatedly halve the search space by comparing boundary and middle elements, updating the minimum candidate accordingly.

Key Insight

If the subarray between l and r is sorted (nums[l] < nums[r]), the minimum is nums[l], and the search can terminate early. Otherwise, the middle element nums[m] is compared to nums[l] to determine which half contains the minimum. Updating res with nums[m] ensures the minimum is tracked even when the minimum lies at mid. Adjusting l or r based on this comparison discards the half that cannot contain the minimum, guaranteeing logarithmic time complexity.

Interview Quick-Check

Core Logic

If nums[l] < nums[r], the subarray is sorted and nums[l] is the minimum; otherwise, use nums[m] to decide which half to discard.

State & Boundaries

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

Common Pitfalls & Bugs

Failing to update res with nums[m] can miss the minimum if it lies at mid.

Complexity

Each iteration reduces the search space by half, leading to O(log n) time complexity.

3

Return the Minimum Element Found

18return res

Objective

To output the smallest element found after the binary search completes.

Key Insight

After the loop terminates, res holds the minimum element found during the search. Returning res provides the correct answer efficiently.

Interview Quick-Check

Core Logic

Return the tracked minimum value res after the search completes.

Line Analysis

This solution has 3 Critical lines interviewers watch for.

Line 7 Critical
if nums[l] < nums[r]:

Check if the current subarray is already sorted.

If nums[l] < nums[r], the subarray is sorted and nums[l] is the minimum, allowing early termination and optimization.

Line 12 Critical
res = min(res, nums[m])

Update the minimum result with the middle element.

Including nums[m] in the minimum check ensures the algorithm does not miss the minimum if it lies at mid.

Line 13 Critical
if nums[m] >= nums[l]:

Check if the middle element is greater than or equal to the left boundary element.

If nums[m] >= nums[l], the left half is sorted, so the minimum must be in the right half, guiding the search direction.

Line 8 Core
res = min(res, nums[l])

Update the minimum result with nums[l] if the subarray is sorted.

Since the subarray is sorted, nums[l] is guaranteed to be the smallest element in this range, so updating res ensures correctness.

Line 14 Core
l = m + 1

Move the left pointer to search the right half.

Discarding the left half by moving l to m + 1 focuses the search on the half that must contain the minimum.

Line 15 Core
else:

Otherwise, move the right pointer to search the left half.

If nums[m] < nums[l], the minimum lies in the left half, so adjusting r to m - 1 narrows the search accordingly.

Line 18 Core
return res

Return the minimum element found after the search completes.

Returning res provides the final answer, which has been updated to the smallest element encountered during the search.

Line 3 Core
res = nums[0]

Initialize the result variable with the first element of the array.

Starting with nums[0] as the initial minimum ensures the algorithm has a baseline to compare against and never returns an uninitialized value.

Line 6 Core
while l <= r:

Begin the binary search loop, continuing while the search space is valid.

The condition l <= r ensures all elements within the current search boundaries are considered, preventing infinite loops and missing elements.

Line 9 Core
break

Break out of the loop as the minimum has been found.

Early termination avoids unnecessary further search, improving efficiency without sacrificing correctness.

Line 11 Core
m = (l + r) // 2

Calculate the middle index of the current search space.

Finding the midpoint divides the search space, enabling binary search to discard half the elements each iteration.

Line 16 Core
r = m - 1

Update the right pointer to narrow the search space.

Adjusting r ensures the search space shrinks correctly, maintaining the binary search invariant.

Line 4 Standard
l, r = 0, len(nums) - 1

Set left and right pointers to the start and end of the array.

These pointers define the current search boundaries for the binary search, covering the entire array initially.

Test Your Understanding

Why does comparing nums[m] with nums[l] allow us to discard half of the search space?

Because if nums[m] >= nums[l], the left half is sorted and the minimum must be in the right half, so we can safely discard the left half by moving l to m + 1; otherwise, the minimum lies in the left half, so we move r to m - 1.

Related Problems

Binary Search pattern

Don't just read it. Drill it.

Reconstruct Find Minimum 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 Find Minimum in Rotated Sorted Array drill

or drill a free problem