地址:https://leetcode.com/problems/search-in-rotated-sorted-array/
题目:
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 ( l o g n ) O(log n) O(logn).
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
理解:
这道题里,给出的数组是一个有序数组经过了旋转,把后面的某些元素移到了最前面,基本的思路应该还是二分查找,但是具体实现的时候肯定有些不同。
看了三种实现比较清楚,总结一下。
实现1:
在这个实现里,首先是使用二分查找找到了最小元素的位置,然后进行二分查找的时候,每次mid都加上这个偏移量,相当于在逻辑上在一个有序数组上进行查找,nb!
这里并没有改变l和h的取值方式,而是通过给mid
加一个偏移量的方法来进行比较。
class Solution {
public:
int search(vector<int>& nums, int target) {
int l = 0, h = nums.size() - 1;
while (l < h) {
int mid = l + (h - l) / 2;
if (nums[mid] > nums[h]) l = mid + 1;
else h = mid;
}
int rot = l;
l = 0;
h = nums.size() - 1;
while (l <= h) {
int mid = l + (h - l) / 2;
int realmid = (mid + rot) % nums.size();
if (nums[realmid] == target) return realmid;
else if (nums[realmid] < target) l= mid + 1;
else h = mid - 1;
}
return -1;
}
};
出处:Concise O(log N) Binary search solution
实现2:
下面的实现,是通过比较改变和target对比的那个数组值。
对于题中给出的数组,若要查找的元素在前半段,可以把后半段都看作是INT_MAX,这样就可以进行二分查找了。同理,若要查找的在后半段,把看作是INT_MIN即可。不需要改变原数组,只需要从逻辑上进行判断。
若target
和nums[mid]
在nums[0]
的同侧,则用nums[mid]和target比较即可,否则,需要
int search(vector<int>& nums, int target) {
int lo = 0, hi = nums.size();
while (lo < hi) {
int mid = (lo + hi) / 2;
double num = (nums[mid] < nums[0]) == (target < nums[0])
? nums[mid]
: target < nums[0] ? -INFINITY : INFINITY;
if (num < target)
lo = mid + 1;
else if (num > target)
hi = mid;
else
return mid;
}
return -1;
}
出处:Clever idea making it simple
实现3:
这种实现也很直观。
- 如果
nums[mid]>nums[r]
,就说明现在的右半段是两个升序数组构成,判断target的大小需要考虑比nums[mid]
大或比nums[r]
小。- 如果满足,说明在右半部分中
- 否则在左半部分中。
- 否则,mid到r是有序的。需要判断target是否在
nums[mid]
-nums[r]
之间。
class Solution {
public:
int search(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1;
while(l <= r){
int mid = l + (r - l) / 2;
if(nums[mid] == target) return mid;
if(nums[mid] > nums[r]){
if(target > nums[mid] || target <= nums[r]) l = mid + 1; // condition for pick right side
else r = mid - 1; // else, pick left side
}else{
if(target <= nums[r] && target > nums[mid]) l = mid + 1; // condition for pick right side
else r = mid - 1; // else, pick left side
}
}
return -1;
}
};
好烦数组的题