字符串旋转与移位
2012-01-07 21:58
218 查看
在好多字符串处理中,旋转与移位是很常见到的,在大规模的数据处理中设计高效的算法是必须的
示例:
把字符串abcdefgh循环左移3位,变为defghabc
输入字符串str与移位数m,输出结果
1、看到题之后一般的想法就是一位一位的移动
abcdefgh
bcdefgha
cdefghab
defghabc
实现代码如下
这样算法的时间复杂度为O(m*n)
2、在第一种方法中是一个字符一个字符的向后移动,这样后边的字符也得跟着移动m次,那么能不能一次就向后移动m个字符呢,答案是肯定的,这就是第二种方法,一次向后移动m个字符
abcdefgh
defabcgh
defghcab
defghabc
示例代码如下:
3、接下来这种方法是利用字符串的翻转
先把字符串按移位的个数分为两部分,abc 与 defgh
思想是先对第一部分反转交换,第一个与最后一个交换,依次类推,交换之后分别为 cba 与 hgfed
最后对所得的字符串cbahgfed整体翻转,结果为defghabc,即我们要得到的结果
实现代码如下:
字符串翻转函数:
4、最后一种方法是用最大公约数法,移动字符
利用公式 index=(i+m*j)%n
设m与n的最大公约数为k,则i为从0到k-1循环k次
如在示例中m=3,n=7,最大公约数为1,所以i只为0
下标计算结果为:0,3,6,2,5,1,4,0
依照这样的顺序进行移位,最后得到最终的结果
实现代码如下:
小结:总共介绍了4中字符串旋转的方法,其中第四种字符移动次数最少
示例:
把字符串abcdefgh循环左移3位,变为defghabc
输入字符串str与移位数m,输出结果
1、看到题之后一般的想法就是一位一位的移动
abcdefgh
bcdefgha
cdefghab
defghabc
实现代码如下
void movebit(string &str,int num) { int len=str.length(); for (int i=0;i<num;++i) { char temp=str[0]; for (int j=1;j<len;++j) { str[j-1]=str[j]; } str[--j]=temp; } }
这样算法的时间复杂度为O(m*n)
2、在第一种方法中是一个字符一个字符的向后移动,这样后边的字符也得跟着移动m次,那么能不能一次就向后移动m个字符呢,答案是肯定的,这就是第二种方法,一次向后移动m个字符
abcdefgh
defabcgh
defghcab
defghabc
示例代码如下:
void movechar(string & ch,int num) { int len=ch.length(); if (len<=0||num>=len) { return; } int first=0; //第一次交换的字符位置 int middle=num; int second=middle; //与之交换的位置 while (1) { char temp=ch[first]; ch[first]=ch[second]; ch[second]=temp; first++; second++; if (first==middle) { if (second>=len) //交换完成,退出 { return; } else //进行下一轮交换 { middle=second; } } else if (second>=len) //前半部分长,后半部分短,如defg abc h { second=middle; } } }
3、接下来这种方法是利用字符串的翻转
先把字符串按移位的个数分为两部分,abc 与 defgh
思想是先对第一部分反转交换,第一个与最后一个交换,依次类推,交换之后分别为 cba 与 hgfed
最后对所得的字符串cbahgfed整体翻转,结果为defghabc,即我们要得到的结果
实现代码如下:
字符串翻转函数:
void revote(char *ch,int start,int end) { char temp; while (start<end) { temp=ch[start]; ch[start]=ch[end]; ch[end]=temp; ++start; --end; } }
void translate(char * ch,int num) { if (ch==NULL||num<=0||num>=strlen(ch)) { return; } revote(ch,0,num-1); //对前一部分翻转 revote(ch,num,strlen(ch)-1); //对后一部分翻转 revote(ch,0,strlen(ch)-1); //整体翻转 }
4、最后一种方法是用最大公约数法,移动字符
利用公式 index=(i+m*j)%n
设m与n的最大公约数为k,则i为从0到k-1循环k次
如在示例中m=3,n=7,最大公约数为1,所以i只为0
下标计算结果为:0,3,6,2,5,1,4,0
依照这样的顺序进行移位,最后得到最终的结果
实现代码如下:
//用辗转相除法求最大公约数函数 int GCD(int m,int n) { if (n==0) { return m; } else { return GCD(n,m%n); } }
void Rotate(string &str,int num) { int len=str.length(); int commonNum=GCD(len,num); //求出的最大公约数 int time=len/commonNum; //计算内循环次数 for (int i=0;i<commonNum;++i) { char temp=str[i]; for (int j=0;j<time-1;++j) { str[(i+j*num)%len]=str[(i+(j+1)*num)%len]; //下标计算 (i+j*num)%len } str[(i+j*num)%len]=temp; } }
小结:总共介绍了4中字符串旋转的方法,其中第四种字符移动次数最少
当然,如果是循环右移m位,可以转变为循环左移n-m位
相关文章推荐
- 【程序员编程艺术】学习记录2:左旋转字符串之循环移位法
- 【转】字符串循环移位(左旋转)问题
- 字符串_旋转_蛮力移位
- 旋转字符串;编程珠玑第二章;rotate a one-dimensional vector;循环移位数组;编程之美
- 数组循环移位(左旋转字符串)
- 字符串旋转词、句子逆序化、字符串移位、最小字典序字符串问题
- 旋转字符串一:暴力移位法
- 旋转字符串(循环移位,rotate)
- 字符串旋转与移位
- alg : 字符串按照字符进行循环移位(左旋转 or 右旋转)
- C语言 判断一个字符串是否为另外一个字符串旋转之后的字符串
- 3.1字符串移位包含的问题
- 3.1——字符串移位包含问题
- 使用移位操作把十进制转换为二进制与十六进制字符串输出
- 左旋转字符串
- 判断子串和判断两个字符串是否由另一个旋转而来的问题
- 字符串之移位
- 字符串移位包含
- 左旋转字符串
- 将一个字符串的前n个字符旋转到后面,采用左旋,或者右旋。