【2010年统考真题】设将n(n>1)个整数存放到一维数组R中。设计一个在时间和空间两方面都尽可能高效的算法。将R中保存的序列循环左移p(0
1)给出算法的基本设计思想。
2)根据设计思想,采用C或C++或Java语言描述算法,关键之处给出注释。
3)说明你所设计算法的时间复杂度和空间复杂度。
(1)可将问题视为把数组ab转换成数组ba,a代表数组的前p个元素,b代表数组中余下的n-p个元素,先将a逆置,再将b逆置,最后将整个再逆置。
(2)算法描述如下:
void Reverse(int R[],int from,int to){
int i,temp;
for(i = 0;i<(to-from-1)/2;i++){
temp = R[from+i];
R[from+i] = R[to-i];
R[to-i] = temp;
}
}
void Converse(int R[],int n,int p){
Reverse(R,0,p-1);
Reverse(R,p,n-1);
Reverse(R,0,n-1);
}
(3)时间复杂度为O(n),空间复杂度为O(1).
另解:借助辅助数组来实现。算法思想:创建大小为p的辅助数组S,将R中前p个整数依次暂存在S中,同时将R中后n-p个整数左移,然后将S中暂存的p个数依次放回到R中的后续单元。时间复杂度为O(n),空间复杂度为O§。
【2011年统考真题】一个长度为L(L>1)的升序序列S,处在第L/2个位置的数成为S的中位数。例如,若序列S1=(11,13,15,17,19),则S1的中位数是15,两个序列的中位数是含它们所有元素的升序序列的中位数。例如,若S2=(2,4,6,8,20),则S1和S2的中位数是11.现在有两个等长升序序列A和B,式设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列A和B的中位数。要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C或C++或Java语言描述算法,关键之处给出注释。
3)说明你所设计算法的时间复杂度和空间复杂度。
(1)因为是两个等长的升序序列,所以总的元素一定是偶数个,通过两两比较,找到第L/2个元素即可。
(2)算法如下:
//自己敲
void search(SeqList A,SeqList B,SeqList &C){
int i,j,k=0
while(i<A.length&&j<B.length){
if(A.data[i]<=B.data[j])
C.data[k++]=A.data[i++];
else
C.data[k++]=B.data[j++];
}
while(i<A.length)
C.data[k++]=A.data[i++];
while(j<B.length)
C.data[k++]=B.data[j++];
C.length=k;
return k/2; //返回中位数
}
(3)时间复杂度和空间复杂度都为O(n)
【2013年统考真题】已知一个整数序列A=(a0,a1,…an-1),其中0<=ai<=n。若存在ap1=ap2=…=apm=x 且m>n/2,则称x为A的主元素。例如A=(0,5,5,3,5,7,5,5),则5为主元素;又如A=(0,5,5,3,5,1,5,7),则A中没有主元素。假设A中的n个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出A的主元素。若存在主元素,则输入该元素;否则输出-1。要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C或C++或Java语言描述算法,关键之处给出注释。
3)说明你所设计算法的时间复杂度和空间复杂度。
(1) 先遍历该数组,标记出可能成为主元素的元素,然后再次扫描,重新计数,判断该元素出现次数是否大于n/2.
第一步:选取候选的主元素。依次扫描所给数组中的每个整数,将第一个遇到的整数Num保存到c中,记录Num出现的次数为1;若遇到的下一个整数仍等于Num,则计数+1,否则计数-1;当计数减到0时,将遇到的下一个整数保存到c中,计数重新记为1,开始新一轮计数。
(2)算法代码如下:
int Majority(int A[],int n){
int i,c,count=1; //c用来保存候选主元素,count用来计数
c=A[0]; //设置A[0]为候选主元素
for(i=1;i<n;i++)
if(A[i]==c)
count++;
else
if(count>0)
count--;
else{
c=A[i];
count=1;
}
if(count>0)
for(i=count=0;i<n;i++)
if(A[i]==c)
count++;
if(count>n/2)
return c;
else
return -1;
}
(3)时间复杂度为O(n),空间复杂度为O(1)
【2018年统考真题】给定一个含n(n>=1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数。例如,数组{-5,3,2,3}中未出现的最小正整数是1;数组{1,2,3}中未出现的最小正整数是4。要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C或C++语言描述算法,关键之处给出注释。
3)说明你所设计算法的时间复杂度和空间复杂度。
(1)从A[0]开始遍历A,若0 (2)算法代码如下:
int findMissMin(int A[],int n){
int i,*B;
B=(int *)malloc(sizeof(int)*n); //分配空间
memset(B,0,sizeof(int)*n);
for(i=0;i<n;i++)
if(A[i]>0&&A[i]<=n)
B[A[i]-1]=1;
for(i=0;i<n,i++)
if(B[i]==0)
break;
return i+1;
}
(3)时间复杂度为O(n),空间复杂度为O(n)
【2020年统考真题】定义三元组(a,b,c)的距离D=|a-b|+|b-c|+|c-a|。给定3个非空整数集合S1、S2、S3,按升序分别存储在3个数组中。请设计一个尽可能搞笑的算法,计算并输出所有可能的三元组(a,b,c)中的最小距离。例如S1={-1,0,9},S2={-25,-10,10,11},S3={2,9,17,30,41},则最小距离为2。要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C或C++语言描述算法,关键之处给出注释。
3)说明你所设计算法的时间复杂度和空间复杂度。
(1)暴力破解,直接三次for循环遍历,用公式带入。
(2)算法代码如下:
//暴力解法
void arr(int S1[],int S2[],int S3[]){
int Length1 = sizeof(S1)/sizeof(S1[0]);
int Length2 = sizeof(S2)/sizeof(S2[0]);
int Length3 = sizeof(S3)/sizeof(S3[0]);
int a,b,c;
a = b = c; //存储三元组
int D=100000; //给出一个超大的值
for(int i=0;i<Length1;i++)
for(int j=0;j<Length2;j++)
for(int k=0;k<Length3;k++)
int dis=abs(S1[i]-S2[j])+abs(S2[j]-S3[k])+abs(S3[k]-S1[i])
if(dis<D){
D=dis;
a=S1[i];
b=S2[j];
c=S3[k];
}
print("%d",D);
print("%d,%d,%d"a,b,c);
}
(3)时间复杂度为O(Length1Length2Length3),空间复杂度为O(1)