1.题目描述
整数数组
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
。你必须设计一个时间复杂度为
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示例 3:
输入:nums = [1], target = 0 输出:-1提示:
1 <= nums.length <= 5000
-104 <= nums[i] <= 104
nums
中的每个值都 独一无二- 题目数据保证
nums
在预先未知的某个下标上进行了旋转-104 <= target <= 104
2.解题思路
当使用二分查找时,我们需要在一个有序数组上进行。但这个数组不是完全有序的,使用mid将它分成left,mid 和 mid,right两个区间时,这两个区间一定有一个是完全有序的。
如果[left,mid]区间有序时,判断taget是否在这个有序区间内,如果是,调整right = mid - 1,到这个有序区间内寻找该值,如果target不在这个有序区间内,调整left = mid + 1,直接到右区间寻找;
如果[mid,right]区间有序时,判断target是否在该区间内,如果在,调整left = mid + 1,到这个有序区间内寻找该值,如果target不在该区间内,right = mid - 1,直接到左区间寻找;
如果left>right,跳出循环仍为找到,说明数组中不存在target,返回-1即可
3.代码实现
class Solution {
public int search(int[] nums, int target) {
int l = 0, r = nums.length - 1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (target == nums[mid]) {
return mid;
}
//如果左区间有序
if (nums[l] <= nums[mid]) {
if (target < nums[l] || target > nums[mid]) {
l = mid + 1;
} else {
r = mid - 1;
}
} else { //否则,右区间有序
if (target < nums[mid] || target > nums[r]) {
r = mid - 1;
} else {
l = mid + 1;
}
}
}
return -1;
}
}