Facebook Pixel

153. Find Minimum in Rotated Sorted Array

Problem Description

You are given an array that was originally sorted in ascending order, but has been rotated between 1 and n times (where n is the length of the array).

A rotation means taking the last element and moving it to the front. For example:

  • Original array: [0,1,2,4,5,6,7]
  • After 1 rotation: [7,0,1,2,4,5,6]
  • After 4 rotations: [4,5,6,7,0,1,2]
  • After 7 rotations: [0,1,2,4,5,6,7] (back to original)

Your task is to find and return the minimum element in this rotated sorted array.

Key requirements:

  • All elements in the array are unique (no duplicates)
  • Your algorithm must run in O(log n) time complexity

The solution uses binary search to efficiently find the minimum element. The key insight is that in a rotated sorted array, the minimum element is at the "pivot point" where the rotation occurred. The algorithm compares elements with nums[0] to determine which half of the array contains the pivot point:

  • If nums[0] <= nums[-1], the array is not rotated (or rotated n times), so the minimum is nums[0]
  • Otherwise, use binary search to find where the rotation break occurs by checking if nums[mid] is greater than or equal to nums[0] to decide which half to search next
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

When we look at a rotated sorted array, we can observe a key pattern: the array can be divided into two sorted portions. For example, in [4,5,6,7,0,1,2], we have [4,5,6,7] and [0,1,2] - both sorted, but there's a "break" between them where the values drop from 7 to 0.

The minimum element will always be at this break point - specifically, it's the first element of the second sorted portion.

Since we need O(log n) time complexity, we can't scan through the entire array. This constraint immediately suggests binary search.

We can define a feasible function: feasible(i) = nums[i] <= nums[n-1]. This creates a pattern of [false, false, ..., true, true, ...] across the array. The first true position is where the minimum element is located.

For example, in [4,5,6,7,0,1,2] with nums[n-1] = 2:

  • feasible(0) = (4 <= 2) → false
  • feasible(1) = (5 <= 2) → false
  • feasible(2) = (6 <= 2) → false
  • feasible(3) = (7 <= 2) → false
  • feasible(4) = (0 <= 2) → true ← first true (minimum at index 4)
  • feasible(5) = (1 <= 2) → true
  • feasible(6) = (2 <= 2) → true

This way, we can use the standard binary search template to find the first index where the condition is true, which gives us the minimum element.

Solution Implementation

1class Solution:
2    def findMin(self, nums: List[int]) -> int:
3        n = len(nums)
4        left, right = 0, n - 1
5        first_true_index = -1
6
7        # Binary search using the template: find first index where nums[mid] <= nums[n-1]
8        while left <= right:
9            mid = (left + right) // 2
10
11            # Feasible condition: nums[mid] <= nums[n-1]
12            if nums[mid] <= nums[n - 1]:
13                first_true_index = mid
14                right = mid - 1
15            else:
16                left = mid + 1
17
18        # first_true_index points to the minimum element
19        return nums[first_true_index]
20
1class Solution {
2    public int findMin(int[] nums) {
3        int n = nums.length;
4        int left = 0;
5        int right = n - 1;
6        int firstTrueIndex = -1;
7
8        // Binary search using the template: find first index where nums[mid] <= nums[n-1]
9        while (left <= right) {
10            int mid = left + (right - left) / 2;
11
12            // Feasible condition: nums[mid] <= nums[n-1]
13            if (nums[mid] <= nums[n - 1]) {
14                firstTrueIndex = mid;
15                right = mid - 1;
16            } else {
17                left = mid + 1;
18            }
19        }
20
21        // firstTrueIndex points to the minimum element
22        return nums[firstTrueIndex];
23    }
24}
25
1class Solution {
2public:
3    int findMin(vector<int>& nums) {
4        int n = nums.size();
5        int left = 0;
6        int right = n - 1;
7        int firstTrueIndex = -1;
8
9        // Binary search using the template: find first index where nums[mid] <= nums[n-1]
10        while (left <= right) {
11            int mid = left + (right - left) / 2;
12
13            // Feasible condition: nums[mid] <= nums[n-1]
14            if (nums[mid] <= nums[n - 1]) {
15                firstTrueIndex = mid;
16                right = mid - 1;
17            } else {
18                left = mid + 1;
19            }
20        }
21
22        // firstTrueIndex points to the minimum element
23        return nums[firstTrueIndex];
24    }
25};
26
1function findMin(nums: number[]): number {
2    const n: number = nums.length;
3    let left: number = 0;
4    let right: number = n - 1;
5    let firstTrueIndex: number = -1;
6
7    // Binary search using the template: find first index where nums[mid] <= nums[n-1]
8    while (left <= right) {
9        const mid: number = Math.floor((left + right) / 2);
10
11        // Feasible condition: nums[mid] <= nums[n-1]
12        if (nums[mid] <= nums[n - 1]) {
13            firstTrueIndex = mid;
14            right = mid - 1;
15        } else {
16            left = mid + 1;
17        }
18    }
19
20    // firstTrueIndex points to the minimum element
21    return nums[firstTrueIndex];
22}
23

Solution Approach

We use the standard binary search template to find the first index where nums[i] <= nums[n-1] is true.

Initial Setup:

left, right = 0, len(nums) - 1
first_true_index = -1

Initialize the search boundaries and a variable to track the first position where the feasible condition is true.

Feasible Function: For any index mid, the feasible condition is: nums[mid] <= nums[n-1]

This creates a pattern like [false, false, false, true, true, true] where we want to find the first true.

Binary Search Loop: Using while left <= right:

  1. Calculate the middle index: mid = (left + right) // 2

  2. Check if feasible (nums[mid] <= nums[n-1]):

    • If true: This could be the minimum or the minimum could be further left. Record first_true_index = mid, then search left with right = mid - 1
    • If false: The minimum must be to the right. Search right with left = mid + 1

Return Result: After the loop, first_true_index holds the index of the minimum element. Return nums[first_true_index].

Edge Case: If the array is not rotated (or rotated n times), the entire array satisfies the feasible condition, so first_true_index will be 0, correctly returning the first element.

Time Complexity: O(log n) - We eliminate half of the search space in each iteration. Space Complexity: O(1) - We only use a constant amount of extra space for the pointers.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's trace through the algorithm with the array [4,5,6,7,0,1,2].

Setup:

  • Array: [4,5,6,7,0,1,2]
  • left = 0, right = 6
  • first_true_index = -1
  • Feasible condition: nums[mid] <= nums[6] (i.e., nums[mid] <= 2)

Iteration 1:

  • left = 0, right = 6
  • mid = (0 + 6) // 2 = 3
  • Check nums[3] = 7 <= 2? No (not feasible)
  • Update: left = mid + 1 = 4

Iteration 2:

  • left = 4, right = 6
  • mid = (4 + 6) // 2 = 5
  • Check nums[5] = 1 <= 2? Yes (feasible)
  • Update: first_true_index = 5, right = mid - 1 = 4

Iteration 3:

  • left = 4, right = 4
  • mid = (4 + 4) // 2 = 4
  • Check nums[4] = 0 <= 2? Yes (feasible)
  • Update: first_true_index = 4, right = mid - 1 = 3

Loop ends (left > right)

Result:

  • first_true_index = 4
  • Return nums[4] = 0

The algorithm correctly identifies that the minimum element 0 is at index 4, which is exactly where the rotation break occurs (between 7 and 0).

Feasibility pattern for this array:

Index:     0      1      2      3      4     5     6
Value:     4      5      6      7      0     1     2
<= 2?:   false  false  false  false  true  true  true

Time and Space Complexity

Time Complexity: O(log n), where n is the length of the input array nums.

The algorithm uses binary search to find the minimum element in a rotated sorted array. In each iteration of the while loop, the search space is reduced by half. The number of iterations is logarithmic with respect to the array size, as we divide the search range by 2 in each step until left >= right. The initial check if nums[0] <= nums[-1] takes O(1) time, and all operations inside the loop (comparison and index calculations) are O(1). Therefore, the overall time complexity is O(log n).

Space Complexity: O(1)

The algorithm uses only a constant amount of extra space. It maintains three integer variables (left, right, and mid) regardless of the input size. No additional data structures are created, and the algorithm operates directly on the input array without recursion (which would use stack space). Thus, the space complexity is constant.

Common Pitfalls

1. Using Wrong Binary Search Template Variant

The Pitfall: Using while left < right with right = mid instead of the standard template:

# INCORRECT variant
while left < right:
    mid = (left + right) // 2
    if nums[mid] > nums[right]:
        left = mid + 1
    else:
        right = mid  # Wrong variant!
return nums[left]

Correct Template Implementation:

first_true_index = -1
while left <= right:
    mid = (left + right) // 2
    if nums[mid] <= nums[n - 1]:
        first_true_index = mid
        right = mid - 1
    else:
        left = mid + 1
return nums[first_true_index]

2. Incorrect Feasible Condition

The Pitfall: Using nums[0] as the reference instead of nums[n-1]:

# INCORRECT - comparing with nums[0]
if nums[mid] < nums[0]:  # This works but requires different logic
    first_true_index = mid
    right = mid - 1

Why This Is Problematic: Using nums[0] requires handling the unrotated array case separately, since all elements satisfy nums[mid] >= nums[0]. Using nums[n-1] creates a cleaner feasible pattern that works for all cases.

Solution: Use nums[n-1] as reference:

if nums[mid] <= nums[n - 1]:
    first_true_index = mid
    right = mid - 1

3. Forgetting first_true_index Initialization

The Pitfall: Not properly handling the case where the array is already sorted (no rotation):

# If array is [1, 2, 3, 4, 5]
# All elements satisfy nums[mid] <= nums[n-1]
# first_true_index will be set on the first iteration

For non-rotated arrays, every element satisfies the feasible condition, so first_true_index will correctly be set to 0 (the index of the minimum).

4. Integer Overflow in Mid Calculation

The Pitfall: Using (left + right) / 2 in languages with fixed integer sizes:

// INCORRECT - can overflow
int mid = (left + right) / 2;

Solution: Use overflow-safe calculation:

int mid = left + (right - left) / 2;
Loading...
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which algorithm is best for finding the shortest distance between two points in an unweighted graph?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More