将一个n元一维向量左移动,或者右移 i个位置,是一道经典的算法题,比如,abcdef左移两位,变成cdefab, 简单的代码使用一个 n元的中间向量完成该工作,能否使用数十个字节的内存空间,用正比于n的时间内完成向量的旋转?
最简单的办法就是,循环移动K次,每次移动一位。时间复杂度是o(K*n)。代码如下:
ShitBits(int *arr,int N,int k)
{
while(k--)
{
int t=arr[N-1];
for(int i=N-1;i>0;i--)
arr[i]=arr[i-1]; //右移
arr[0]=t;
}
}
很明显,如此代码段,还是比较费力的,我们完全有更快的办法。下面是一个杂技算法,时间复杂度大约O(t* t),,高人算一下,本人估算不太准确(这个和希尔排序有点像,我不太会算)。算法如下:
首先,要先用欧几里得算法求最大公约数:
int gcd(int i,int j)
{
while(i!=j)
{
if(i>j)
i-=j;
else
j-=i;
return i;
}
}
这个时间复杂度是O(logN)。虽然算法比较慢,但是也够用了。
杂技算法如下:
for(int i=0;i<gcd(rotdist,n);i++)
{
t=x[i];
j=i;
while(1)
{
int k=j+rotdist;
if(k>=n)
k-=n;
if(k==i)
break;
x[j]=x[k];
j=k;
}
x[j]=t;
}
算法的基本思想就是将字符串想象成为了一个标准环路,结果,依次将x[i]移动 rotdist个位置,一直到最后。这样逐次移动每个字符串,一共移动 gcd次。大大减少了移动次数。但是速度还是很慢。还有更高速的移动方法。