33. 搜索旋转排序数组
题目描述
升序排列的整数数组 nums
在预先未知的某个点上进行了旋转(例如, [0,1,2,4,5,6,7]
经旋转后可能变为 [4,5,6,7,0,1,2]
)。
请你在数组中搜索 target
,如果数组中存在这个目标值,则返回它的索引,否则返回 -1
。
示例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 ≤ n u m s . l e n g t h ≤ 5000 1 \le nums.length \le 5000 1≤nums.length≤5000
- − 1 0 4 ≤ n u m s [ i ] ≤ 1 0 4 -10^4 \le nums[i] \le 10^4 −104≤nums[i]≤104
- nums 中的每个值都 独一无二
- nums 肯定会在某个点上旋转
- − 1 0 4 ≤ t a r g e t ≤ 1 0 4 -10^4 \le target \le 10^4 −104≤target≤104
题解:
此题肯定是二分,但是怎么二分大有学问。
参考 在有序旋转数组中找到最小值 ,两题基本一样,核心思想没变。
欢迎尝试进阶版(带重复值):在有序旋转数组中找到一个数
法一:
两次二分,先确认 target
在哪个区间(找到分界点),然后再该区间上进行普通的二分即可。
也就是 把复杂问题分解成简单的子问题 。
法一代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
int n = nums.size();
int l = 0, r = n - 1, m;
if ( nums[n - 1] < nums[0] ) {
while ( l < r ) {
m = ( l + r ) >> 1;
if ( nums[m] >= nums[0] ) l = m + 1;
else r = m;
}
if ( target <= nums[n - 1] ) r = n - 1;
else l = 0, --r;
}
while ( l < r ) {
m = (l + r) >> 1;
if ( nums[m] == target ) return m;
if ( nums[m] > target ) r = m;
else l = m + 1;
}
return nums[r] == target ? r : -1;
}
};
/*
时间:4ms,击败:92.60%
内存:10.7MB,击败:98.53%
*/
法二:
一次二分,在二分中添加一些判断,确认 target
在哪个区间:
-
若
nums[mid] >= nums[0]
,说明mid
在左边区间:- 若
target >= nums[l] && target <= nums[mid]
,说明此时需要在区间[l,mid]
上查找,即r = mid
; - 若
target < nums[l] || target > nums[mid]
,说明target
在mid
右边,即l = mid + 1
- 若
-
若
nums[mid] < nums[0]
,说明此时mid
在右边区间:-
若
target <= nums[mid] || target > nums[n - 1]
,说明target
在mid
左边, 即r = mid
-
否则的话,说明
target
在mid
右边,即l = mid + 1
-
法二代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
int n = nums.size();
int l = 0, r = n - 1, m;
while ( l < r ) {
m = ( l + r ) >> 1;
if ( nums[m] == target ) return m;
if ( nums[m] >= nums[0] ) {
if ( target >= nums[0] && target <= nums[m] ) r = m;
else l = m + 1;
} else {
if ( target <= nums[m] || target > nums[n - 1] ) r = m;
else l = m + 1;
}
}
return nums[r] == target ? r : -1;
}
};
/*
时间:4ms,击败:92.60%
内存:10.8MB,击败:97.18%
*/