假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [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
方法1、双指针+根据规则的if-else:
这种方法应该是不符合本题的时间复杂度,但又不同于直接顺序遍历
用于铺垫二分查找解法。
根据旋转的规则,旋转点可能出现在数组中间,也可能出现旋转后数组不变的情况
假设旋转点出现在数组中间:
nums[i]-num[i-1]>0
,当小于0时,则为旋转边界。如果到达边界都没有找到,说明查找的数不在数组中,此时返回-1,如果查找过程中找到target则返回数组下标。
从high开始向左遍历情况类似。假设旋转点出现在数组之外:
特例判断:
方法2、二分查找:
在上面一个方法中,虽然划分了数组,但比较过程仍然只是线性遍历
我们可以进一步利用二分查找来进行搜索
class Solution {
public int search(int[] nums, int target) {
int len = nums.length;
if(nums==null||len==0) return -1;
int low = nums[0];
int high = nums[len-1];
if(target==low) return 0;
if(target==high) return len-1;
if(len==1) return nums[0]==target?nums[0]:-1;
if(low<high){
for(int i=0;i<len-1;i++){
if(target==nums[i]) return i;
}
}else{
if(target>low){
for(int i=1;i<len-1;i++){
if(target==nums[i]) return i;
if(nums[i]-nums[i-1]>0){
continue;
}else{
break;
}
}
}else if(target<high){
for(int i=len-1;i>=0;i--){
if(target==nums[i]) return i;
if(nums[i]-nums[i-1]>0){
continue;
}else{
break;
}
}
}
}
return -1;
}
}
class Solution {
public int search(int[] nums, int target) {
int len = nums.length;
int left = 0, right = len-1;
while(left<=right){
int mid = (left+right)/2;
if(nums[mid]==target)
return mid;
else if(nums[mid]<nums[right]){ // 如果中间数小于右边,说明右边有序
if(nums[mid]<target && target<=nums[right])
left = mid+1; // 缩小左边查找区间
else
right = mid-1;
}
else{// 如果中间数大于右边,说明左边有序
if(nums[left]<=target && target<nums[mid])
right = mid-1; // 缩小右边查找区间
else
left = mid+1;
}
}
return -1;
}
}
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有