- 寻找旋转排序数组中的最小值 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
解答
因为有可能左、右、中间都相等,所以需要两边分别二分看
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 { public: int myMin(vector<int>& nums, int left, int right) { if (left >= right || nums[left] < nums[right]) { return nums[left]; } int mid = (left + right) / 2; if (nums[left] == nums[right]) { if (nums[mid] < nums[left]) { return myMin(nums, left, mid); } if (nums[mid] > nums[left]) { return myMin(nums, mid + 1, right); } return min(myMin(nums, left, mid - 1), myMin(nums, mid + 1, right)); } else { if (nums[mid] < nums[right]) { return myMin(nums, left, mid); } if (nums[mid] > nums[right]) { return myMin(nums, mid + 1, right); } return min(myMin(nums, left, mid - 1), myMin(nums, mid + 1, right)); } }
int findMin(vector<int>& nums) { return myMin(nums, 0, nums.size() - 1); } };
|
可以优化一下合并中间的对left right大小的判断:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public: int myMin(vector<int>& nums, int left, int right) { if (left >= right || nums[left] < nums[right]) { return nums[left]; } int mid = (left + right) / 2; if (nums[mid] < nums[right]) { return myMin(nums, left, mid); } if (nums[mid] > nums[right]) { return myMin(nums, mid + 1, right); } return min(myMin(nums, left, mid - 1), myMin(nums, mid + 1, right)); }
int findMin(vector<int>& nums) { return myMin(nums, 0, nums.size() - 1); } };
|
非递归的做法
(题解里面提到的)在left、right、mid对应的都相等的时候,不是分别算求min,而是将r–
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public: int findMin(vector<int>& nums) { int left = 0, right = nums.size() - 1; while (true) { if (left >= right || nums[left] < nums[right]) { return nums[left]; } int mid = (left + right) / 2; if (nums[mid] < nums[right]) { right = mid; } else if (nums[mid] > nums[right]) { left = mid + 1; } else { right--; } } } };
|