153.寻找旋转排序数组中的最小值
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7]
可能变为 [4,5,6,7,0,1,2]
)。
请找出其中最小的元素。
你可以假设数组中不存在重复元素。
示例 1:
输入: [3,4,5,1,2] 输出: 1
示例 2:
输入: [4,5,6,7,0,1,2] 输出: 0
解题思路:
二分法。
注意:
旋转排序数组的定义:将第i个点以后的所有只移动到数组的最前面,这些被移动的点不改变先后顺序。也就意味着如果这个i是最后一个点,那么数组将不是旋转的。
class Solution { public: int findMin(vector<int>& nums) { int size = nums.size(); if (size == 1) return nums[0]; if (nums[0] < nums[size - 1]) return nums[0]; data = nums; return find(0, size - 1); } int find(int first, int second) {//闭区间 if (first == second) return data[second]; if (first + 1 == second) return data[second]; int min = data[second]; int mid = data[(first + second) / 2]; if (mid > min) return find((first + second) / 2, second); if (mid < min) return find(first, (first + second) / 2); } private: vector<int> data; }; |
154.寻找旋转排序数组中的最小值II
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7]
可能变为 [4,5,6,7,0,1,2]
)。
请找出其中最小的元素。
注意数组中可能存在重复的元素。
示例 1:
输入: [1,3,5] 输出: 1
示例 2:
输入: [2,2,2,0,1] 输出: 0
说明:
- 这道题是 寻找旋转排序数组中的最小值 的延伸题目。
- 允许重复会影响算法的时间复杂度吗?会如何影响,为什么?
解题思路:
二分法。与无重复数组相比,唯一多的可能是中间位置的值可能和最右端相等,这个时候最小值是不确定,可能在左,可能在右。需要逐个计算,取最小。代码中加黑的部分就是和153题的区别。 时间上看会慢一点点,你可以认为是进行了两次二分,复杂度还是log(n)。
class Solution { public: int findMin(vector<int>& nums) { int size = nums.size(); if (size == 1) return nums[0]; if (nums[0] < nums[size - 1]) return nums[0]; data = nums; return find(0, size - 1); } int find(int first, int second) {//闭区间 if (first == second) return data[second]; if (first + 1 == second) return data[second]; int min = data[second]; int mid = data[(first + second) / 2]; if (mid == min) { int sgn1 = find((first + second) / 2, second); int sgn2 = find(first, (first + second) / 2); return (sgn1 < sgn2 ? sgn1 : sgn2); } if (mid > min) return find((first + second) / 2, second); if (mid < min) return find(first, (first + second) / 2); } private: vector<int> data; }; |