微软(运算):
一个数组是由一个递减数列左移若干位形成的,比如{4,3,2,1,6,5}
一个数组是由一个递减数列左移若干位形成的,比如{4,3,2,1,6,5}
是由{6,5,4,3,2,1}左移两位形成的,在这种数组中
#include<iostream>
#include<cassert>
#include<stack>
using namespace std ;
int FindNumberInLeftShiftSequence(int *A,int nLen,int expectedNum)
{
assert(A!=NULL&&nLen>0);
int start=0;
int end=nLen-1;
while(start<=end)
{
int mid=start+((end-start)>>2);
if(expectedNum==A[mid])
return mid;
if (A[mid]<A[start])
{
if(expectedNum>A[mid])
end=mid-1;
else
start=mid+1;
}
else if(A[mid]>A[start])
{
if(expectedNum<A[mid])
start=mid+1;
else
end=mid-1;
}
else
{
for (int i=start;i<mid;i++)
{
if(A[i]==expectedNum)
return i;
}
start=mid+1;
}
}
return -1;
}
int main()
{
int A[]={6,5,4,3,2,1};
int nLen=sizeof(A)/sizeof(int);
cout<<FindNumberInLeftShiftSequence(A,nLen,0)<<endl;
int B[]={1,1,1,1,0,1};
int nLen2=sizeof(B)/sizeof(int);
cout<<FindNumberInLeftShiftSequence(B,nLen2,0);
return 1;
}
思路:在此序列不断二分的过程中,由于原序列是一个递减序列经过旋转得到的,将它从任何位置分开,都会得到两个序列,其中一个是递减序列,另一个可以通过一个递减序列通过旋转得到。这样在不断地二分查找时,我们处理的序列子片段要么就是一个旋转后递减序列,要么就是一个纯递减序列,而无论是前者还是后者,在继续分成两个片段时,至少有一个纯递减序列(可能两个都是,如果之前的序列片段就是纯递减序列的话)。这样我们可以保证能找到一个片段是纯递减序列(if(data[i]>=data[j])),然后判断我们要找的数是否在这个片段中(这是很直观的,if(data[i]<=num&&num<=data[j])),如果在则继续在此片段中查找,否则说明在另一个序列中,则递归在其中查找
代码:
#include<iostream>
using namespace std;
int bisearch(int a[],int left,int right,int num)
{
if(a==NULL||right<0)
return -1;
if(left==right)
{
if(a[left]==num)
return left;
else
return -1;
}
int mid=(left+right)/2;
if(a[mid]==num)
return mid;
if(a[mid]<=a[left])
{
if(num>a[mid]&&num<=a[left])
return bisearch(a,left,mid-1,num);
else
return bisearch(a,mid+1,right,num);
}
else
{
if(num>=a[right]&&num<a[mid])
return bisearch(a,mid+1,right,num);
else
return bisearch(a,left,mid-1,num);
}
}
int main()
{
int a[100]={4,3,2,1,6,5};
cout<<bisearch(a,0,5,3)<<endl;
return 0;
}