Introduction to the Problem
The "Find Minimum in Rotated Sorted Array" problem is a classic algorithmic challenge frequently encountered in technical interviews and competitive programming. In this problem, you are given an array of unique integers that was originally sorted in ascending order but then rotated at some pivot point unknown to you. Your task is to find the minimum element in the array.
For example, if the original array is [0, 1, 2, 4, 5, 6, 7] and it is rotated at pivot index 3, it becomes [4, 5, 6, 7, 0, 1, 2]. The minimum element here is 0.
This problem matters because it tests your understanding of array manipulation and your ability to adapt standard algorithms to modified scenarios. While a simple linear search can solve it in O(n) time, the optimal solution requires a modified binary search that operates in O(log n) time. Mastering this demonstrates a strong grasp of algorithmic optimization and problem-solving skills.
Understanding the Algorithm
Linear Search vs. Binary Search
The most straightforward approach is to iterate through the array and keep track of the smallest element found. This linear search approach has a time complexity of O(n). However, because the array retains a partially sorted structure, we can do much better.
Binary search is traditionally used on fully sorted arrays to find an element in O(log n) time. In a rotated sorted array, the array consists of two sorted subarrays. The minimum element is the only element that is smaller than its previous element. By comparing the middle element with the rightmost element, we can determine which half of the array contains the minimum.
The Binary Search Logic
The core idea relies on comparing the middle element (mid) with the rightmost element (right):
- If
nums[mid] > nums[right], the minimum must be in the right half. This is because a larger middle element compared to the right element indicates that the rotation point (and thus the minimum) lies somewhere betweenmid + 1andright. - If
nums[mid] < nums[right], the minimum must be in the left half, includingmiditself. The array frommidtorightis sorted, so the minimum could be atmidor somewhere to its left.
We continue narrowing down the search space until left and right pointers converge, at which point left will point to the minimum element.
Step-by-Step Implementation in JavaScript
Let's translate this logic into JavaScript. We will use a while loop to maintain our left and right pointers.
Complete Code Example
/**
* Finds the minimum element in a rotated sorted array.
* @param {number[]} nums - The rotated sorted array of unique integers.
* @return {number} The minimum element in the array.
*/
function findMin(nums) {
let left = 0;
let right = nums.length - 1;
// If the array is not rotated (or has only one element),
// the first element is the minimum.
if (nums[left] <= nums[right]) {
return nums[left];
}
while (left < right) {
// Calculate the middle index.
// Math.floor((left + right) / 2) can cause overflow in some languages,
// but is safe in JS. Alternatively, left + Math.floor((right - left) / 2) is safer.
let mid = left + Math.floor((right - left) / 2);
// If the middle element is greater than the rightmost element,
// the minimum is in the right half.
if (nums[mid] > nums[right]) {
left = mid + 1;
}
// Otherwise, the minimum is in the left half (including mid).
else {
right = mid;
}
}
// When left == right, we have found the minimum element.
return nums[left];
}
// Example usage:
const rotatedArray = [4, 5, 6, 7, 0, 1, 2];
console.log(findMin(rotatedArray)); // Output: 0
const notRotatedArray = [1, 2, 3, 4, 5];
console.log(findMin(notRotatedArray)); // Output: 1
const singleElementArray = [1];
console.log(findMin(singleElementArray)); // Output: 1
Best Practices and Edge Cases
When implementing this algorithm, it is important to consider several best practices and potential edge cases to ensure your code is robust:
- Handle Empty Arrays: Although the problem usually assumes a non-empty array, it is good practice to add a check at the beginning of your function:
if (nums.length === 0) return -1;or throw an error. - Prevent Integer Overflow: While JavaScript handles large numbers safely up to
Number.MAX_SAFE_INTEGER, usingleft + Math.floor((right - left) / 2)instead ofMath.floor((left + right) / 2)is a good habit that prevents integer overflow in other programming languages like Java or C++. - Check for Non-Rotated Arrays: Before entering the
whileloop, checking ifnums[left] <= nums[right]allows you to return early if the array is already sorted normally, optimizing the best-case scenario to O(1). - Duplicate Elements: The solution above assumes all elements are unique. If the array can contain duplicates (e.g.,
[2, 2, 2, 0, 1]), the time complexity degrades to O(n) in the worst case. Whennums[mid] === nums[right], you cannot determine which half contains the minimum, so you must decrementrightby 1 (right--) to safely reduce the search space.
Conclusion
Solving the "Find Minimum in Rotated Sorted Array" problem is an excellent exercise in adapting binary search to non-standard scenarios. By understanding how to compare the middle element with the boundaries to discard half of the search space, you can achieve an efficient O(log n) solution. Remembering to handle edge cases like non-rotated arrays and potential duplicates will make your implementation robust and production-ready. With this step-by-step guide, you are now well-equipped to tackle this problem and similar variations in your coding interviews and projects.