yichao firstname, zeaster nickname, zhang lastname

编写一个函数,作用是把一个char组成的字符串循环右移n个

例如,"abcdef"循环右移2个就变为"efabcd"

popo实现了一个,不过需要O(n)的额外空间
程序:
void LoopMove(char * pStr,int steps)
{
int len = strlen(pStr);
char *s = new char[len+1];
int count = 0;
char *temp = pStr;
while (*pStr)
{
s[(count+steps)%len] = *pStr;
pStr++;
count++;
}
s[len] = '\0';
strcpy(temp,s);
delete []s;
}


最近想出了个空间为O(1),时间为O(n)的算法
就是只通过数组指针移动和交换来实现

int LoopMove2(char *p, int i, int t, int s, int m){
int n = strlen(p);
int j = (i+m)%n;
if(t == j) return 0;
p[s] = p[j];
p[j] = p[t];
LoopMove2(p, j, s, t,m);
}

使用方法是
如果要右移2位就调用
LoopMove2(p,0,0,-1,2);

基本思想是:
如果数组X有n个元素,要右移m个位置
申请一个临时变量,设它为数组上的X[-1]
对于数组中的Xi,要把它一次性移到它的最终位置,这个位置是j=(i+m)%n,那么首先把Xj移到X[-1],然后把X[i]移到X[j],接下来一次性移动Xj到它的最终位置(j+m)%n,此时临时变量为X[i],要移动的元素是Xj,并且Xj的值在X[-1]位置上。
由此定义LoopMove2函数,它参数的含义是
i:此步要移动的元素Xi
t:当前元素Xi的值在数组上的位置
s:临时变量在数组上的位置
m:右移的位数

最终移动的终止条件是:
当前元素Xi的值在数组上的位置==Xi要移向的最终位置

这个程序中使用了数组的-1处作为临时变量的位置,主要是想把程序写得简单些
当然这样会带来一些问题,但作为说明性的例子就暂不考虑了。
gmail id: yichao.zhang
欢迎和各位讨论算法

No comments: