排序旋转数组查找(Search in a sorted, rotated list)

来源:互联网 发布:用u盘重装mac系统 编辑:程序博客网 时间:2024/05/23 14:34

假设存在一个按升序排列的数组A,让A绕其中的一个元素旋转180度得到新的数组A1,如何在对数时间复杂度内完成对A1的查找呢?

对于A1这样的数组,我们仍可使用二分查找来找寻其中的元素,只是,在二分查找之前,需要找到其分界点,这样分界点的两边分别为增序数组,从而可以使用二分查找。因此上述问题的主要操作就是在找寻这个分界点。

例如a[6] = {4,5,6,1,2,3}这样的数组,我们需要找到元素6的索引,如何查找呢?首先我们可以设定一个最大值max为数组的最后一个元素,6左边的元素均大于max,6右边的元素均小于max,为此进行二分查找,如果a[mid]<max,则此时mid位于6的右边,因此将high=mid;如果a[mid]>max,则说明此时mid在6的左边,将low=mid,于此同时将max=a[mid],如果a[mid]=max说明此时max=6,返回mid

代码实现

int find_point(const int* a, const int n){int low = 0;int high = n-1;int max = a[n-1];while (low<high){int mid = (low+high)/2;if(a[mid] < max)high = mid;else if(a[mid] > max){max = a[mid];low = mid;}else{return mid;}}return -1;}

上述查找分界点的时间为O(logn)。找到分界点之后即可利用二分查找来查询目标元素。

代码实现

int binary_search(const int* a, int low, int high, int target){while (low<=high){int mid = (low + high)/2;if(a[mid] == target)return mid;else if(a[mid] > target)high = mid-1;elselow = mid+1;}return -1;}int find_target(const int* a, const int n,const int target){int point = find_point(a,n);if(point == -1)return -1;if(target >= a[0])return binary_search(a,0,point,target);elsereturn binary_search(a,point+1,n-1,target);}

测试代码

using namespace std;int find_point(const int* a, const int n);int binary_search(const int* a, int low, int high, int target);int find_target(const int* a, int n, int target);void main(){int a[] = {5,6,7,8,1,2,3,4};int n=8;for(int i=0; i<n; i++)cout<<a[i]<<" ";cout<<endl;int target;cout<<"Target: ";cin>>target;while(target>=0){cout<<"Location: "<<find_target(a,n,target)<<endl;cout<<"Target: ";cin>>target;}}
仅供参考考,欢迎拍砖

0 0