一、问题描述:
设有非降序整数序列A=a1, a2, ..., an,则整数序列B=ak+1,..., an, a1,..., ak(1<=k<=n)是序列A的一个旋转序列,当k=n时序列B与序列A相同。给定一旋转序列a[0, 1, ..., n-1],求该序列的最小值。
二、问题求解:
直接二分法搜索。设头指针f,尾指针r,中间指针m=(f+r)/2,则有如下求解过程:
设f=0, r=n-1:
1. 若f小于r,则令m=(f+r)/2,转2;否则,返回a[f],算法结束;
2. 若a[m]大于a[r],则最小值指针pos必在m之后,此时应将f更新为m+1,转1;否则,最小值指针pos必在m或m之前,此时应将r更新为m,转1;
由于循环执行条件是f小于r,故每次循环后,必有f(变大)或r(变小)得到更新,故能保证算法结束。
三、代码实现:
各函数作用如下:
void swap(int &a,int &b);//交换变量a,b的值
int cmp(const void *a,const void *b);//比较a,b所指单元的值的大小,并将数组a非递减排列;
void reverse(int *a,int beg,int end);//将数组a的区间[beg,end]位置上的数据逆置;
void init_arr(int *a,int n);//初始化数组a,随机生成数据,并将数组a非递减排列;
void print_arr(int *a,int n);//打印数组a;
int min_arr(int *a,int n);//寻找旋转序列中的最小值;
void rotate_arr(int *a,int n,int k);//对数组a进行旋转,向右旋转k个单位;
<pre name="code" class="cpp">#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cassert>
void swap(int &a,int &b);
int cmp(const void *a,const void *b);
void reverse(int *a,int beg,int end);
void init_arr(int *a,int n);
void print_arr(int *a,int n);
int min_arr(int *a,int n);
void rotate_arr(int *a,int n,int k);
int main(int argc,char *argv[]){
const int SIZE=20;
int a[SIZE];
init_arr(a,SIZE);
print_arr(a,SIZE);
printf("min:%d\n",min_arr(a,SIZE));
rotate_arr(a,SIZE,5);
print_arr(a,SIZE);
printf("min:%d\n",min_arr(a,SIZE));
return 0;
}
void swap(int &a,int &b){
a^=b;b^=a;a^=b;
}
int cmp(const void *a,const void *b){
return *(int*)a-*(int*)b;
}
void reverse(int *a,int beg,int end){
while(beg<end){
swap(a[beg++],a[end--]);
}
}
void init_arr(int *a,int n){
srand(time(NULL));
for(int i=0;i<n;++i){
a[i]=rand()%20;
}
qsort(a,n,sizeof(int),cmp);
}
void print_arr(int *a,int n){
printf("##begin##\n");
for(int i=0;i<n;++i){
printf("%d ",a[i]);
}
printf("\n##end##\n");
}
int min_arr(int *a,int n){
assert(a!=NULL&&n>0);
int f=0,r=n-1,m;
while(f<r){
m=(f+r)>>1;
if(a[m]>a[r]){
f=m+1;
}else{
r=m;
}
}
return a[f];
}
void rotate_arr(int *a,int n,int k){
if(a==NULL||n<1||k<1||k>=n){
return;
}
reverse(a,0,k-1);
reverse(a,k,n-1);
reverse(a,0,n-1);
}
四、测试结果:
<pre name="code" class="cpp">##begin##
0 1 2 3 3 3 4 6 6 7 7 9 9 13 13 13 17 17 18 18
##end##
min:0
##begin##
3 4 6 6 7 7 9 9 13 13 13 17 17 18 18 0 1 2 3 3
##end##
min:0