[LeetCode]110. Find Minimum in Rotated Sorted Array旋转数组最小值
Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
Find the minimum element.
You may assume no duplicate exists in the array.
解法1:顺序查找,时间复杂度O(n)。
class Solution { public: int findMin(vector<int>& nums) { int minVal = INT_MAX; for(int i = 0; i < nums.size(); ++i) { minVal = min(minVal, nums[i]); } return minVal; } };
解法2:因为数组是从有序数组旋转得到的,而有序数组的查找可以使用二分查找,因此本题也可以尝试使用二分查找。因为数组是由升序数组旋转得到,并且无重复值,因此:(1)如果数组首元素小于数组尾元素,则数组实际未旋转,返回首元素即可;(2)如果不是情况(1)则必有数组首元素大于数组尾元素。此时找到数组的中间元素,再分几种情况:(2.1)数组首元素小于数组中间元素,此时说明前半部分数组是有序的,且最小元素必在后半部分;(2.2)数组首元素大于数组中间元素,此时数组后半部分有序,且最小元素在前半部分。对这两种情况都可以递归调用二分查找解决。
class Solution { public: int findMin(vector<int>& nums) { int n = nums.size(); if (n <= 1) return n == 1 ? nums[0] : 0; return binaryFind(nums, 0, n - 1); } private: int binaryFind(vector<int>& nums, int left, int right) { if (nums[left] < nums[right]) return nums[left]; if (left == right) return nums[left + 1]; int mid = (left + right) >> 1; if (nums[left] < nums[mid]) left = mid; else right = mid; return binaryFind(nums, left, right); } };
left总是指向前面递增数组的元素,而right总是指向后面递增数组的元素。最终left将指向前面递增数组的最后一个元素,而right则指向后面递增数组的第一个元素,因此最终left+1=right,返回结果。如果存在旋转,则最终right所指就是整个数组的最小元素。循环形式代码:
class Solution { public: int findMin(vector<int>& nums) { int n = nums.size(), left = 0, right = n - 1, mid = 0; if (n <= 1) return n == 1 ? nums[0] : 0; while (nums[left] >= nums[right]) { if (right == left + 1) return nums[right]; mid = (left + right) >> 1; if (nums[left] < nums[mid]) left = mid; else right = mid; } return nums[mid]; } };