读程序员编程艺术第一章---左旋字符串(三)
2014-03-18 10:19
344 查看
STL中的循环移位法用到了gcd原理。gcd原理的实现是简单的欧几里得算法又称辗转相除法,这里就不在赘述了。
对于数组的循环移位,可以采用的方法一共有四种。
1、将数组拷贝复制到相同长度的数组之中,改变顺序,并拷贝回原来的数组。
2、先交换前面的能够交换的部分,在处理尾巴。如上一遍中的指针翻转法就是这么做的。
3、分组交换。
4、所有序号为(j+i*m)%n(j表示循环的起始链位置,i为计数变量,m为左旋位数,n表示字符串长度),会构成一个循环链(共有gcd(n,m)个),每个循环链上的元素只要移动一个位置既可,最后整个过程一共交换了n次(每一个循环链长n/gcd(n,m),总共有gcd(n,m)个循环链)。
下面我们来看一个简单的例子:
字符串abcd需要左旋维dabc,可以知道n=4,m=3。
根据4中的方法:
1、j=0,即起始位置为0;
2、得到循环链
for i=0:n-1
int k=i*m%n;
end;
得到循环链是0,3,2,1
3、我们根据这个循环序列复制一遍即可得到想要的结果。
temp=ch[0],ch[0]=hc[3],ch[3]=ch[2],ch[2]=ch[1],ch[1]=temp;
即abcd-->_bcd-->dbc_-->db_c-->d_bc-->dabc;
很奇妙是吧。
上面是对于m,n互为质数的情况,现在我们讨论一下m,n不是互为质数情况。此时循环链不止一个,我们只要把每个循环链依次的执行一遍既可以得到我们想要的结果。所有序号为(j+i*m)%n(其中j为0到gcd(n,m)-1之间的某一个数,i=0:n-1)会构成一个循环,一共有gcd(n,m)个循环链。
可以编写代码 如下:
对于数组的循环移位,可以采用的方法一共有四种。
1、将数组拷贝复制到相同长度的数组之中,改变顺序,并拷贝回原来的数组。
2、先交换前面的能够交换的部分,在处理尾巴。如上一遍中的指针翻转法就是这么做的。
3、分组交换。
4、所有序号为(j+i*m)%n(j表示循环的起始链位置,i为计数变量,m为左旋位数,n表示字符串长度),会构成一个循环链(共有gcd(n,m)个),每个循环链上的元素只要移动一个位置既可,最后整个过程一共交换了n次(每一个循环链长n/gcd(n,m),总共有gcd(n,m)个循环链)。
下面我们来看一个简单的例子:
字符串abcd需要左旋维dabc,可以知道n=4,m=3。
根据4中的方法:
1、j=0,即起始位置为0;
2、得到循环链
for i=0:n-1
int k=i*m%n;
end;
得到循环链是0,3,2,1
3、我们根据这个循环序列复制一遍即可得到想要的结果。
temp=ch[0],ch[0]=hc[3],ch[3]=ch[2],ch[2]=ch[1],ch[1]=temp;
即abcd-->_bcd-->dbc_-->db_c-->d_bc-->dabc;
很奇妙是吧。
上面是对于m,n互为质数的情况,现在我们讨论一下m,n不是互为质数情况。此时循环链不止一个,我们只要把每个循环链依次的执行一遍既可以得到我们想要的结果。所有序号为(j+i*m)%n(其中j为0到gcd(n,m)-1之间的某一个数,i=0:n-1)会构成一个循环,一共有gcd(n,m)个循环链。
可以编写代码 如下:
#include"stdafx.h" #include<stdio.h> #include"string" #include"iostream" using namespace std; //求最大公因数 int gcd(int m,int n) { //递归出口 if(m%n==0) return n; else { //设置临时变量,防止m丢失 int temp=m; m=n; n=temp%n; //递归 gcd(m,n); } } //定义左旋函数 void rotate(string &str,int m) { //字符串长度 int lenofStr=str.length(); //循环链的个数,也即是外层循环的次数 int numofGroup=gcd(lenofStr,m); //每个循环链的个数,也即是内层循环的次数 int elemInSub=lenofStr/numofGroup; for(int j=0;j<numofGroup;j++) { char temp=str[j]; int i; //一次循环链的交换 for(i=0;i<elemInSub-1;i++) { str[(j+i*m)%lenofStr]=str[(j+(i+1)*m)%lenofStr]; } str[(j+i*m)%lenofStr]=temp; } } int main() { string str="abcdef"; cout<<str<<endl; rotate(str,3); cout<<str<<endl; return 0; }
相关文章推荐
- 读程序员编程艺术第一章---左旋字符串
- 读程序员编程艺术第一章---左旋字符串(二)
- 【程序员编程艺术】第一章:左旋转字符串
- 程序员编程艺术(算法卷):第一章、左旋转字符串
- 程序员编程艺术_第一章左旋转字符串_C实现
- 程序员编程艺术(算法卷):第一章、左旋转字符串探讨
- 程序员编程艺术(算法卷):第一章、左旋转字符串
- 程序员编程艺术第一章、左旋转字符串
- 程序员编程艺术第一章、左旋转字符串
- 程序员编程艺术第一章、左旋转字符串
- 程序员编程艺术第一章、左旋转字符串
- 程序员编程艺术:第一章、左旋转字符串
- 程序员编程艺术(算法卷):第一章、左旋转字符串
- 程序员编程艺术:第一章、左旋转字符串
- 程序员编程艺术:第一章、左旋转字符串
- 程序员编程艺术:第一章、左旋转字符串
- 算法题002 程序员编程艺术第一章 左旋转字符串
- 程序员编程艺术学习笔记(一)字符串左旋问题
- 程序员编程艺术(算法卷):第一章、左旋转字符串
- 程序员编程艺术(算法卷):第一章、左旋转字符串