【问题描述】设将n(n>1)个整数存放在一维数组R中。试设计一个在时间和空间两方面都尽可能高效的算法。将R中保存的序列循环左移P(P>0)个位置。
例如,假设P<n,将R中的数据(X0,X1…..Xn-1)循环左移P个位置后,变换为(Xp, Xp+1,…..Xn-1,X0,X1……Xp-1)
【测试样例】R={0,1,2,3,4,5,6} p=3
【输出结果】3 4 5 6 0 1 2
算法思路一:
- 将数组R(X0,X1…..Xn-1)分成两部分(X0,X1,……Xp-1),(Xp, Xp+1,…..Xn-1)对这两部分中的元素分别进行逆置
- 中间结果为(Xp-1,Xp-2,......X1,X0),(Xn-1,Xn-2,......Xp-1,Xp),再对整个数组进行逆置
- 最终结果为(Xp, Xp+1,…..Xn-1,X0,X1……Xp-1)
由于要求中有时间空间两方面尽可能高效,上述算法的空间复杂度为O(1),采用逆置算法时间复杂度为O(n)
//数组的逆置算法
void reverse_all(int R[],int n)
{
int temp,i;
for(i=0;i<n/2;i++)
{
temp=R[i];
R[i]=R[n-1-i];
R[n-1-i]=temp;
}
}
//部分逆置算去
void reverse(int R[],int start,int end)
{
int temp,i;
for(i=0;i<(end-start+1)/2;i++)
{
temp=R[start+i];
R[start+i]=R[end-i];
R[end-i]=temp;
}
}
//调用三次部分逆置算法可以完成本题
void converse_p1(int R[],int p,int n)
{
reverse(R,0,p-1);
reverse(R,p,n-1);
reverse(R,0,n-1);
}
算法思路二:
- 借助辅助数组T暂存需要逆置的部分(X0,X1,……Xp-1)
- 将数组R中的(Xp, Xp+1,…..Xn-1)部分向前移动
- 将辅助数组中T的元素填入数组R后,(Xp, Xp+1,…..Xn-1,X0,X1……Xp-1)
上述算法的空间复杂度为O(n),采用移动和赋值算法时间复杂度为O(n)
//使用辅助数组完成本题
void converse_p2(int R[],int p,int n)
{
int i;
int T[p];
for(i=0;i<p;i++)
{
T[i]=R[i];
}
for(i=p;i<n;i++)
{
R[i-p]=R[i];
}
for(i=0;i<p;i++)
{
R[n-p+i]=T[i];
}
}