假设存在一个按升序排列的数组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;
else
low = 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);
else
return 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;
}
}
仅供参考考,欢迎拍砖