Search in Rotated Sorted Array (M)
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
Your algorithm’s runtime complexity must be in the order of O(log n).
Example 1:
Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4
Example 2:
Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4
题意
将一递增数列的随机后半部分与前半部分换位,得到新数组,在新数组中查找目标值。
思路
比较简单的做法是先用一个二分找到两个递增序列的边界,再用一个二分在对应的递增序列里查找目标值。
也可以只用一个二分完成操作:求出mid,先考虑mid落在右递增区间的情况,如果target也落在右递增区间且比nums[mid]大,说明只需要继续向右查找,令 left = mid + 1 即可,不然只要向左查找,令 right = mid - 1;同理,对于mid落在左递增区间的情况进行处理。

代码实现 - 不求边界
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
return mid;
}
// 通过与第一个值相比较来判断mid落在左区间还是右区间
if (nums[mid] < nums[left]) {
if (target <= nums[right] && target > nums[mid]) {
left = mid + 1;
} else {
right = mid - 1;
}
} else {
if (target >= nums[left] && target < nums[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
}
return -1;
}
}
代码实现 - 先求边界
class Solution {
public int search(int[] nums, int target) {
if (nums.length == 0) {
return -1;
}
int left = 0;
int right = nums.length - 1;
int split = nums.length - 1; // 默认不存在边界
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
return mid;
}
if (nums[mid] >= nums[left]) {
if (mid + 1 < nums.length && nums[mid + 1] < nums[mid]) {
split = mid;
break;
} else {
left = mid + 1;
}
} else {
if (mid - 1 >= 0 && nums[mid - 1] > nums[mid]) {
split = mid - 1;
break;
} else {
right = mid - 1;
}
}
}
// 选择一个递增区间进行二分查找
if (target >= nums[0]) {
return binarySearch(nums, 0, split, target);
} else {
return binarySearch(nums, split + 1, nums.length - 1, target);
}
}
private int binarySearch(int[] nums, int left, int right, int target) {
while (left <= right) {
int mid = (left + right) / 2;
if (target > nums[mid]) {
left = mid + 1;
} else if (target < nums[mid]) {
right = mid - 1;
} else {
return mid;
}
}
return -1;
}
}
本文介绍了一种在旋转后的有序数组中查找目标值的算法。数组原本按升序排列,但未知位置进行了旋转。通过一次或两次二分查找,可以在O(logn)的时间复杂度内找到目标值或返回-1。文章提供了两种实现方式:一种是先找到两个递增序列的边界,然后在相应的序列中查找;另一种是直接在一个二分查找中完成整个过程。
854

被折叠的 条评论
为什么被折叠?



