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 rotatedntimes), so the minimum isnums[0] - Otherwise, use binary search to find where the rotation break occurs by checking if
nums[mid]is greater than or equal tonums[0]to decide which half to search next
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)→ falsefeasible(1) = (5 <= 2)→ falsefeasible(2) = (6 <= 2)→ falsefeasible(3) = (7 <= 2)→ falsefeasible(4) = (0 <= 2)→ true ← first true (minimum at index 4)feasible(5) = (1 <= 2)→ truefeasible(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]
201class 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}
251class 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};
261function 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}
23Solution 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:
-
Calculate the middle index:
mid = (left + right) // 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 withright = mid - 1 - If false: The minimum must be to the right. Search right with
left = mid + 1
- If true: This could be the minimum or the minimum could be further left. Record
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 EvaluatorExample 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 = 6first_true_index = -1- Feasible condition:
nums[mid] <= nums[6](i.e.,nums[mid] <= 2)
Iteration 1:
left = 0,right = 6mid = (0 + 6) // 2 = 3- Check
nums[3] = 7 <= 2? No (not feasible) - Update:
left = mid + 1 = 4
Iteration 2:
left = 4,right = 6mid = (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 = 4mid = (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;
Which algorithm is best for finding the shortest distance between two points in an unweighted graph?
Recommended Readings
https assets algo monster cover_photos Binary_Search svg Binary Search Intuition Binary search is an efficient array search algorithm It works by narrowing down the search range by half each time If you have looked up a word in a physical dictionary you've already used binary search in real life Let's
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion If you prefer videos here's a video that explains recursion in a fun and easy way Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask him
Want a Structured Path to Master System Design Too? Don’t Miss This!