LeetCode解题 33:Search in Rotated Sorted Array
Problem 33: Search in Rotated Sorted Array [Medium]
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 = 3
Output: -1
来源:LeetCode
解题思路
- 基本思路是利用二分查找,每层递归排除掉一半的数值。
- 难点在于条件判断,需要考虑要查找的
target
会不会因为排序数组的旋转而不在原本二分查找的那半段范围。为了方便说明,将头尾相接处称为断崖
,二分点下标称为p
,以下为需要分类讨论的情况:
a. 假设nums[p] < target
,说明目标值较大,正常情况下需要查找数组的右半部分,此时应有nums[right] > target
,需要查找p+1 ~ right-1
;
b. 当nums[right] < target
时,与正常情况不同,是需要讨论的重点。按断崖
所在的位置进行分类讨论。
b1. 寻找断崖
所处位置的方法是比较nums[right]
与nums[p]
的值,如果nums[right] < nums[p]
,则说明断崖
在p ~ right
之间,即最大的尾部处于这之间,要找的目标值比nums[p]
大,就可以在p+1 ~ right-1
之间查找。(例如在[4,5,6,7,8,9,1,2,3]中寻找9的第一次二分查找。)
b2. 如果nums[right] > nums[p]
,则说明p ~ right
之间是严格升序的,断崖
应该在left ~ p
之间,因此既比nums[p]
大又比nums[right]
大的目标值就应该在left ~ p-1
之间查找。(例如在[7,8,9,1,2,3,4,5,6]中寻找9的第一次二分查找。)
c. 上述数值比较过程中如果有正好相等的情况则之间返回下标即可。如果有left > right
的情况则说明查找失败,返回-1。 - 数组个数为0或仅剩1个数且不为
target
时直接返回-1。
二分查找时间复杂度O(log n)。
要点:二分查找
、条件判断
Solution (Java)
class Solution {
public int search(int[] nums, int target) {
int N = nums.length;
if(N == 0) return -1;
return partSearch(nums, 0, N-1, target);
}
private int partSearch(int[] nums, int left, int right, int target){
if(left > right) return -1;
if(left == right && nums[left] != target) return -1;
int len = right - left + 1;
int p = left + len/2;
if(nums[p] == target){
return p;
}
else if(nums[p] < target){
if(nums[right] == target){
return right;
}
else if(nums[right] > target){
return partSearch(nums, p+1, right-1, target);
}
else{
if(nums[right] < nums[p]){
// 断崖在p~right之间
return partSearch(nums, p+1, right-1, target);
}
else{
// 断崖在另半部分
return partSearch(nums, left, p-1, target);
}
}
}
else{
if(nums[left] == target){
return left;
}
else if(nums[left] < target){
return partSearch(nums, left+1, p-1, target);
}
else{
if(nums[left] > nums[p]){
// 断崖在left~p之间
return partSearch(nums, left+1, p-1, target);
}
else{
// 断崖在另半部分
return partSearch(nums, p+1, right, target);
}
}
}
}
}
修改过程
- 在碰到b情况时,想当然觉得
断崖
在另半部分,直接去搜索了另半部分,因此输入[7,8,1,2,3,4,5,6],2时,应该返回3,却错误地返回了-1。