设计一个算法 把一个含有N个元素的数组循环右移K位 要求时间复杂度为O(N ) 且只允许使用两个附加变量
方法1:
将长度为N的数组 每次移动一位 移动k次 如abc移动三次 为abc ->cab->bca->abc. 当移动为N此时 与原数组相同 因此 当k>N 时 移动结果与 k%N 相同
for (int i=0;i<k%N;i++)
{
char t=a[0];
for(int j=0;j<strlen(a)-1;j++)
{
a[j]=a[j+1];
}
a[strlen(a)-1]=t;
}
方法2:
将长度为N的数组 (a0,a1,a2...ak) (ak+1,ak+2...aN)循环右移K 位 移动后结果为 (ak+1,ak+2...aN)(a0,a1,a2...ak)
可以看做是 A=a0,a1,a2...ak,B=ak+1,ak+2...aN
A逆排序后为 A‘=aK,ak-1,...a0,A‘B
B逆排序后为B’=aN,aN-1....ak+1,A’B‘
全部逆排序后为BA=ak+1,ak+2....aN,a0,a1....ak
char *xmov(char *a,int k)
{
char t;
int kk=k-1;
for(int i=0,j=kk;i<j ;i++,j--)
{
t=a[j];
a[j]=a[i];
a[i]=t;
}
for(int i=k,j=strlen(a)-1;i<j && i<strlen(a);i++,j--)
{
t=a[j];
a[j]=a[i];
a[i]=t;
}
for(int i=0,j=strlen(a)-1;i<j;i++,j--)
{
cout<<a[i]<<' '<<a[j]<<endl;
t=a[i];
a[i]=a[j];
a[j]=t;
}
return a;
}
方法三:利用gcd 原理
将a[0]存储到临时变量t 将a[k%n]移动到a[0] 将a[2*k%n] 移动到 a[r%n]。。。。将a[x*k%n]移动到a[(x-1)*k%n] 直到x*k%n==0 将a[x*k/n]=t
如果 该过程不能移动完所有元素 那么需要从a[1]继续移动 总共重复gcd(n,k)次
int n=gcd(k,strlen(a));
for( int i=0;i<n ;i++)
{
int j=i;
t=a[j];
while(1)
{
if((j+k)%n== i)
break;
else
a[j]=(j+k)%n;
j=(j+k)%n;
}
a[j]=t;
}