本文已参与「新人创作礼」活动,一起开启掘金创作之路。
搜索旋转排序数组 II
81. 搜索旋转排序数组 II - 力扣(LeetCode) (leetcode-cn.com)
已知存在一个按非降序排列的整数数组 nums ,数组中的值不必互不相同。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转 ,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如,[0,1,2,4,4,4,5,6,6,7]在下标 5 处经旋转后可能变为 [4,5,6,6,7,0,1,2,4,4] 。
给你 旋转后 的数组 nums 和一个整数 target ,请你编写一个函数来判断给定的目标值是否存在于数组中。如果 nums 中存在这个目标值 target ,则返回 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
提示:
- 1 <= nums.length <= 5000
- -10^4 <= nums[i] <= 10^4
- 题目数据保证 nums 在预先未知的某个下标上进行了旋转
- -10^4 <= target <= 10^4
进阶:
这是 搜索旋转排序数组 的延伸题目,本题中的 nums 可能包含重复元素。
这会影响到程序的时间复杂度吗?会有怎样的影响,为什么?
解题思路
虽然这里数组是排好序的数组被旋转了,但既然被排过序了,就要看怎么能利用它排序的特性。
- 同样设置参数left,right,mid,以及一个容器vector,同时设置一个辅助函数来进行正常的二分查找
- mid对应的数字如果大于left对应的数字,就说明左边是排好序的,否则右边是排好序的,在这里要注意一些边界问题,比如等于,等于是无法判断有没有排好序的,例如 1 0 1 1 1.所以遇到这样的情况,只需要简单的把与mid相等的left+1或者right-1.
- 除此之外在while函数循环里面,如果target就在排好序的范围内,就把该子串assign给新建的容器,进行二分查找,否则调整对应的left和right,知道left大于right,跳出循环返回FALSE
- 此处还有一个小细节,就是数组长度只有两位,容易把结果判错,因为主要跳出while循环就会return FALSE,所以我们应该在while刚开始进行一个判断,如果mid==target,return TRUE,这样这种情况就规避了。
代码实现
class Solution {
public:
bool search1(vector<int>& nums, int target){
int left = 0, right = nums.size()-1;
while(left <= right){
int mid = (left + right) / 2;
if(nums[mid] == target)return true;
else if(nums[mid] > target){
right = mid - 1;
}
else left = mid + 1;
}
return false;
}
bool search(vector<int>& nums, int target) {
int left = 0, right = nums.size()-1;
vector<int> nums1;
while(left <= right){
int mid = (left + right) / 2;
if(nums[mid] == target || nums[left] == target || nums[right] == target)return true;
if(nums[mid] > nums[left]){
if(target >= nums[left] && target <= nums[mid]){
nums1.assign(nums.begin()+left, nums.begin()+mid+1);
return search1(nums1, target);
}
else left = mid + 1;
}
else if(nums[mid] < nums[right]){
if(target >= nums[mid] && target <= nums[right]){
nums1.assign(nums.begin()+mid, nums.begin()+right+1);
return search1(nums1, target);
}
else right = mid - 1;
}
else if(nums[mid] == left){
left = left + 1;
}
else{
right = right - 1;
}
}
return false;
}
};