1. 题目

https://leetcode.cn/problems/search-in-rotated-sorted-array/
考察点
这道题的考察点是二分查找的应用。二分查找是一种在有序数组中查找目标值的高效算法,它的时间复杂度是O(log n)。二分查找的基本思想是,每次比较中间元素和目标值的大小,根据比较结果缩小搜索范围,直到找到目标值或者搜索范围为空。
这道题的难点是,给定的数组不是完全有序的,而是在某个点旋转过的。这就需要我们先找到旋转点,然后根据目标值和数组最后一个元素的大小关系,确定搜索范围是在旋转点的左边还是右边。这两个步骤都可以用二分查找来实现。最后,在搜索范围内用二分查找来找到目标值。
这道题考察了我们对二分查找的理解和灵活运用
2. 解法
思路
LeetCode 33题是在一个旋转有序数组中搜索一个目标值,如果找到了返回它的索引,否则返回-1。要求算法的时间复杂度是O(log n)。
你可以用二分查找的思想来实现这个问题。首先,找到数组中的最小值的索引,这个索引就是旋转的点。然后,根据目标值和数组的最后一个元素的大小关系,确定搜索的范围是在旋转点的左边还是右边。最后,在搜索的范围内用二分查找来找到目标值。
代码逻辑
- 首先,我要找到数组中的最小值的索引,这个索引就是旋转的点。我用二分查找的方法来找,比较中间元素和最后一个元素的大小,如果中间元素大于最后一个元素,说明最小值在右半部分,否则在左半部分。这样不断缩小搜索范围,直到找到最小值的索引。
- 然后,我要确定搜索目标值的范围是在旋转点的左边还是右边。我用目标值和数组的最后一个元素的大小关系来判断,如果目标值小于等于最后一个元素,说明目标值在旋转点右边的升序部分,否则在左边的升序部分。这样我就可以确定搜索范围的起始和结束位置。
- 最后,在搜索范围内用二分查找来找到目标值。比较中间元素和目标值的大小,如果相等就返回索引,如果中间元素小于目标值,说明目标值在右半部分,否则在左半部分。这样不断缩小搜索范围,直到找到目标值或者搜索范围为空。
具体实现
public class Solution {
public int search(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int minIdx = findMinIdx(nums); //找到旋转点
if (target == nums[minIdx]) {
return minIdx;
}
int m = nums.length;
int start = (target <= nums[m - 1]) ? minIdx : 0; //确定搜索范围
int end = (target > nums[m - 1]) ? minIdx : m - 1;
while (start <= end) { //二分查找
int mid = start + (end - start) / 2;
if (nums[mid] == target) {
return mid;
} else if (target > nums[mid]) {
start = mid + 1;
} else {
end = mid - 1;
}
}
return -1;
}
private int findMinIdx(int[] nums) { //找到旋转点
int start = 0;
int end = nums.length - 1;
while (start < end) {
int mid = start + (end - start) / 2;
if (nums[mid] > nums[end]) {
start = mid + 1;
} else {
end = mid;
}
}
return start;
}
}
浙公网安备 33010602011771号