代码题(27)— 搜索旋转排序数组、搜索旋转排序数组 II、寻找旋转排序数组中的最小值 II
1、154. 寻找旋转排序数组中的最小值 II
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7]
可能变为 [4,5,6,7,0,1,2]
)。
请找出其中最小的元素。
注意数组中可能存在重复的元素。
class Solution { public: int findMin(vector<int>& nums) { if(nums.empty()) return -1; int low = 0; int high = nums.size()-1; while(low<=high) { int mid = (low+high)/2; if(nums[mid]>nums[high]) low = mid+1; else if(nums[mid]<nums[high]) high = mid; // 此处不能-1,因为mid可能就是最小值 else high--; } return nums[low]; } };
2、33、搜索旋转排序数组
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7]
可能变为 [4,5,6,7,0,1,2]
)。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1
。
你可以假设数组中不存在重复的元素。
你的算法时间复杂度必须是 O(log n) 级别。
示例 1:
输入: nums = [4,5,6,7,0,1,2]
, target = 0
输出: 4
示例 2:
输入: nums = [4,5,6,7,0,1,2]
, target = 3
输出: -1
思路:二分搜索法的关键在于获得了中间数后,判断下面要搜索左半段还是右半段,我们观察上面红色的数字都是升序的,由此我们可以观察出规律,如果中间的数小于最右边的数,则右半段是有序的,若中间数大于最右边数,则左半段是有序的,我们只要在有序的半段里用首尾两个数组来判断目标值是否在这一区域内,这样就可以确定保留哪半边了,
class Solution { public: int search(vector<int>& nums, int target) { if(nums.size() == 0) return -1; int low = 0, high = nums.size()-1; while(low<=high) { int mid=(low+high)*0.5; if(nums[mid] == target) return mid; else if(nums[mid] > nums[high])//中间值大于最右边的数,则左半段是有序的 { if(nums[low] <= target && nums[mid] > target) high = mid-1; else low = mid+1; } else { if(nums[mid] < target && nums[high] >= target) //中间值小于最右边的数,则右半段是有序的 low = mid+1; else high = mid-1; } } return -1; } };
3、81. 搜索旋转排序数组 II
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,0,1,2,2,5,6]
可能变为 [2,5,6,0,0,1,2]
)。
编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true
,否则返回 false
。
示例 1:
输入: nums = [2,5,6,0,0,1,2]
, target = 0
输出: true
示例 2:
输入: nums = [2,5,6,0,0,1,2]
, target = 3
输出: false
进阶:
- 这是 搜索旋转排序数组 的延伸题目,本题中的
nums
可能包含重复元素。 - 这会影响到程序的时间复杂度吗?会有怎样的影响,为什么?
现在数组中允许出现重复数字,这个也会影响我们选择哪半边继续搜索,由于之前那道题不存在相同值,我们在比较中间值和最右值时就完全符合之前所说的规律:如果中间的数小于最右边的数,则右半段是有序的,若中间数大于最右边数,则左半段是有序的。而如果可以有重复值,就会出现来面两种情况,[3 1 1] 和 [1 1 3 1],对于这两种情况中间值等于最右值时,目标值3既可以在左边又可以在右边,那怎么办么,对于这种情况其实处理非常简单,只要把最右值向左一位即可继续循环,如果还相同则继续移,直到移到不同值为止,然后其他部分还采用 Search in Rotated Sorted Array 在旋转有序数组中搜索 中的方法。
class Solution { public: bool search(vector<int>& nums, int target) { int res = false; if(nums.empty()) return res; int low = 0; int high = nums.size()-1; while(low <= high) { int mid = (low+high)/2; if(nums[mid] == target) return true; else if(nums[mid]>nums[high]) { if(nums[mid] >target && nums[low] <= target) high = mid-1; else low = mid+1; } else if(nums[mid] < nums[high]) { if(nums[mid] < target && nums[high] >= target) low = mid+1; else high = mid-1 ; } else high--; } return res; } };