LC 153 - Find Minimum in Rotated Sorted Array
Question
Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums = [0,1,2,4,5,6,7] might become:
[4,5,6,7,0,1,2]if it was rotated4times.[0,1,2,4,5,6,7]if it was rotated7times.
Notice that rotating an array [a[0], a[1], a[2], ..., a[n-1]] 1 time results in the array [a[n-1], a[0], a[1], a[2], ..., a[n-2]].
Given the sorted rotated array nums of unique elements, return the minimum element of this array.
You must write an algorithm that runs in O(log n) time.
Example 1:
1
2
Input: nums = [3,4,5,1,2]
Output: 1
Explanation: The original array was [1,2,3,4,5] rotated 3 times.
Example 2:
1
2
Input: nums = [4,5,6,7,0,1,2]
Output: 0
Explanation: The original array was [0,1,2,4,5,6,7] and it was rotated 4 times.
Example 3:
1
2
Input: nums = [11,13,15,17]
Output: 11
Explanation: The original array was [11,13,15,17] and it was rotated 4 times.
Constraints:
n == nums.length1 <= n <= 5000-5000 <= nums[i] <= 5000- All the integers of
numsare unique. numsis sorted and rotated between1andntimes.
Links
Question here and solution here
Solution
concept
We use binary search on this problem despite the array is rotated: but part of the array is still sorted.
There are 2 parts of the array that is continuous, e.g. [3,4,5,1,2] has [3,4,5] and [1,2] and notice that the all elements in left part is always bigger than those in the right part due to rotation. We can use these properties.
Specifically, we still initialize l and r pointer as usual at the 2 ends of the array and we will maintain an ans variable to keep track the minimum value so far.
- if
nums[mid] >= nums[l], it means thatnums[mid]belongs to the left portion and we should search right for smaller value (=becauselandmidcould be the same) - if the above is false, then we should search the left
- if we notice
nums[l] < nums[r]means we are already in an array that is already sorted, thennums[l]should be used to compare to the last updatedansto give the final answer (we could have overshot and the correct answer is already captured inans).
Notice there is a variation of binary search called lower bound where we do not track ans separately and use while l < r. We update r = m such that we do not over step and skip.
code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution:
def findMin(self, nums: List[int]) -> int:
l, r = 0, len(nums) - 1
ans = float("inf")
while l <= r:
mid = (l + r)//2
ans = min(ans, nums[mid])
if nums[l] < nums[r]:
return min(ans,nums[l])
break
elif nums[mid] >= nums[l]:
l = mid + 1
else:
r = mid - 1
return ans
class Solution:
"""
notice the l < r
this is also called lower bound binary search
"""
def findMin(self, nums: List[int]) -> int:
l, r = 0, len(nums) - 1
while l < r:
m = l + (r - l) // 2
if nums[m] < nums[r]:
r = m
else:
l = m + 1
return nums[l]
Complexity
time: $O(\log n)$
space: $O(1)$