33. 搜索旋转排序数组
33. 搜索旋转排序数组
整数数组 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,5,6,7]
在下标 3
处经旋转后可能变为 [4,5,6,7,0,1,2]
。
给你 旋转后 的数组 nums
和一个整数 target
,如果 nums
中存在这个目标值 target
,则返回它的下标,否则返回 -1
。
示例 1:
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4
示例 2:
输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1
示例 3:
输入:nums = [1], target = 0
输出:-1
你可以设计一个时间复杂度为 O(log n)
的解决方案吗?
提示:
1 <= nums.length <= 5000
-10^4 <= nums[i] <= 10^4
nums
中的每个值都 独一无二- 题目数据保证
nums
在预先未知的某个下标上进行了旋转 -10^4 <= target <= 10^4
思路:
题目希望我们使用一个时间复杂度为 O(log n)
的解决方案,自然是想到二分查找。
如果要使用二分,那就先用二分找到最小值也就是旋转的点在哪里。
找到后就可以判断在前半段还是后半段进行判断了
class Solution {
public:
int search(vector<int>& nums, int target) {
int n=nums.size();
if(n==1)return target==nums[0]?0:-1;
int lo=0;
int ri=n-1;
while(lo<ri){
int mid=lo+(ri-lo)/2;
if(nums[mid]>nums[ri])lo++;
else ri--;
}
int index=lo;//lo指向排序前的最小元素位置
//index就是切分点
if(target>nums[n-1]&&index-1>=0){//大于最后一个数,说明在前半段 注意这里要给出index-1>=0的限制不然会越界 如果出现越界情况 你会发现说明数组就没有旋转
lo=0;
ri=index-1;
}else{//在后半段或者数组没有旋转
lo=index;
ri=n-1;
}
while(lo<ri){
int mid=lo+(ri-lo)/2;
if(nums[mid]==target)return mid;
else if(nums[mid]<target)lo++;
else ri--;
}
return target==nums[lo]?lo:-1;
}
};
本文来自博客园,作者:{BailanZ},转载请注明原文链接:https://www.cnblogs.com/BailanZ/p/16272395.html