LeetCode 33.搜索旋转排序数组
Posted KyrieLiu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 33.搜索旋转排序数组相关的知识,希望对你有一定的参考价值。
解法一:顺序查找
时间复杂度:O(n)
int search(vector<int>& nums, int target) {
for(int i=0;i<nums.size();i++){
if(nums[i]==target) return i;
}
return -1;
}
解法二:二分查找
分析:
题目进阶中,要求设计一个O(logn)的方案,根据时间复杂度,在查找方案中很容易想到二分查找。
但与正常的二分查找不同,该数组是在某个下标 k
下进行了旋转,因此,在二分查找时,需要做一些特定的处理。
假设数组旋转之前为:【0 1 2 4 5 6 7】
旋转之后可能是(k=3):【4 5 6 7 0 1 2】
普通的二分查找:
前提:有序序列
将待查找序列根据中间元素
mid
,将序列划分为[low,mid-1]
、mid
和[mid+1,high]
。
- 如果待查找元素
target==nums[mid]
,代表查找成功,返回mid
- 如果
target < nums[mid]
,则在左半部分[low,mid-1]
继续二分查找- 如果
target > nums[mid]
,则在右半部分[mid+1,high]
继续二分查找直到找到与target相等元素的位置,或发现序列中不存在与target相等的值
时间复杂度:O(logn)
普通二分查找的代码:
//普通二分 int binarySearch(vector<int>& nums, int target){ if(nums.size()==0) return -1; int low=0,high=nums.size()-1; while(low<=high){ int mid = low + (high-low)/2; //避免low+high越界 if(nums[mid]==target) return mid; else if(nums[mid]<target) low=mid+1; else high=mid-1; } //结束条件:low>high return -1; }
经过旋转后的数组,只是局部有序,整体并不有序,那么本题如何应用二分?
与普通的二分查找一样,根据中间元素
mid
,将序列划分为[low,mid-1]
、mid
和[mid+1,high]
。不同的是,在比较
target
和nums[mid]
之前,先比较nums[low]
和nums[mid]
的关系,原理如下:第一类序列:【2 3 4 5 6 7 1】,也就是
nums[low] < nums[mid]
,此例中为2<5。这种情况下,可以保证序列的前半部分是有序的。
- 如果
nums[low] <= target < nums[mid]
,则去前半部分找- 否则,去后半部分找
第二类序列:【6 7 1 2 3 4 5】,也就是
nums[low] > nums[mid]
,此例中为6>2。这种情况下,可以保证序列的后半部分是有序的。
- 如果
nums[mid] <= target < nums[end]
,则去后半部分找- 否则,去前半部分找
代码:
int rotateBinarySearch(vector<int>& nums, int target){
if(nums.size()==0) return -1;
int low=0,high=nums.size()-1;
while(low<=high){
int mid = low+(high-low)/2;
if(nums[mid]==target) return mid;
else if(nums[low]<=nums[mid]){ //下面两个if中 target一定不等于 nums[mid],因为是从上面的if过来的
if(nums[low]<=target && target<nums[mid]){ //mid\'s left
high=mid-1;
}else { //mid\'s right
low=mid+1;
}
}else { //nums[low]>nums[mid]
if(nums[mid]<target && target<=nums[high]){ //right
low=mid+1;
}else { //left
high = mid-1;
}
}
}
return -1;
}
以上是关于LeetCode 33.搜索旋转排序数组的主要内容,如果未能解决你的问题,请参考以下文章