Follow up for "Find Minimum in Rotated Sorted Array":
What if duplicates are allowed?Would this affect the run-time complexity? How and why?
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.
The array may contain duplicates.
解法1:本题旋转数组最小值的扩展,这次数组中可以存在重复元素了。上题因数组中无重复元素,因此通过判断nums[left]和nums[mid]的大小可以确定[left,mid]之间是否是严格递增的,而当存在重复元素时就不能这样简单的确定了。比如数组{0,1,1,1,1}的两种旋转{1,0,1,1,1}和{1,1,1,0,1},第一次迭代时nums[left]=nums[mid]=nums[right],这样不能确定不能确定[left,mid)或者(mid,right]是不是升序,也不知道最小元素0是在[left,mid]还是[mid,right]之中。因此当left、mid、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]) { mid = (left + right) >> 1; if (nums[left] == nums[mid] && nums[mid] == nums[right]) return *min_element(nums.begin() + left, nums.begin() + right + 1); else if (nums[mid] <= nums[right]) right = mid; else left = mid + 1; } return nums[left]; } };
解法2:当left、mid、right三者所指数组元素相同时,可以将left右移一位,跳过这个相同元素,这样并不会影响结果,因为这个元素还有另外的副本存在与剩下的数组中。注意输入数组有两种情况:要么nums[left]<nums[right],此时数组未被旋转,可以直接返回;要么nums[left]>=nums[right],这时数组被旋转过。
class Solution { public: int findMin(vector<int>& nums) { int n = nums.size(), left = 0, right = n - 1, mid = 0; if (n == 0) return 0; while (left < right) { if(nums[left] < nums[right]) return nums[left]; mid = (left + right) >> 1; if (nums[left] < nums[mid]) left = mid + 1; else if (nums[left] > nums[mid]) right = mid; else ++left; } return nums[right]; } };