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 。
解题心路及存在的问题
解题心路
- 该题要求以O(logn)的复杂度解决 所以我们优先想到二分法
- 通过二分法找到最小值所在的索引 我的算法只能求存在旋转的数组 若是在0或length-1的位置旋转(即与原数组没有区别 则会出现bug)
- 然后再通过二分查找找到target的索引
问题:
- 首先就是二分查找的逻辑还是不熟练 导致出现了数组越界的问题
- 由于算法缺陷 (即上方2位置) 我需要先判断是否是旋转过的数组 (ps: lc上明明说了一定会旋转 结果旋转等于没旋的也算上了 那还不如不说)
public static int search(int[] nums, int target) {
if (nums.length == 0) {
return -1;
}
if (nums[0] > nums[nums.length-1]){
int minIndex = getMinIndex(nums);
if (target > nums[0]) {
return binarySearch(nums, 0, minIndex - 1, target);
} else if (target < nums[0]) {
return binarySearch(nums, minIndex, nums.length - 1, target);
} else return 0;
}else {
return binarySearch(nums,0,nums.length - 1,target);
}
}
public static int binarySearch(int[] nums, int low, int high, int target) {
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (nums[mid] == target) {
return mid;
}
if (nums[mid] > target) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
public static int getMinIndex(int[] nums) {
int low = 0;
int high = nums.length - 1;
if (high == 0) return 0;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (nums[mid] > nums[mid + 1]) {
return mid+1;
}
if (nums[mid] < nums[0]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return 0;
}