把学过的东西记下来,因为我记性不好!
一:对左旋转字符串的两种我比较中意的解法:
(1):三次翻转法,代码如下:
#include <iostream>
using namespace std;
void m_reverse(char* start, char* end){
char tmp;
while(start < end){
tmp = *start;
*start = *end;
*end = tmp;
start++; end--;
}
}
// 为了支持链式表达,返回旋转后的首地址
char* m_rotate(char* str, int num, int len){
char* retV = str;
m_reverse(&str[0], &str[num-1]);
m_reverse(&str[num], &str[len-1]);
m_reverse(&str[0], &str[len-1]);
return retV;
}
int main(int argc, char* argv[])
{
char testStr[] = "abcdefghij";
cout << m_rotate(testStr, 4, 10) << endl;
return 0;
}
(2):仿stl::rotate 算法,代码如下:
/*
此算法相对前面的三次翻转法理解上有一定的难度
(i+j*num)%len 这些位置上的字符会构成一个循坏
链,且只需要往前移动一个位置便得到字符正确
的位置(可以动手举几个简单的例子来观察其规律)
这里我证明一下有多少个这样循环链?每个循环链
有多少个元素?:
从 (i+j*num)%len 这个式子可以看出,当 j*num 为
num与len的最小公倍数时,对一个链来说它开始循
环,所以有:(len*num)/gcd(len, num) = j*num(a, b
的最小公倍数为 (a*b)/gcd(a, b)), 由以上解得:
j = len/gcd(len, num), 所以每个链的长度为:
len/gcd(len, num) ,轻松推出:共有gcd(len, num)
条链。
*/
#include <iostream>
using namespace std;
//求最大公约数
int gcd(int m, int n){
int r;
while((r = m % n) != 0){
m = n;
n = r;
}
return n;
}
char* m_rotate(char* str, int num, int len){
char* retV = str;
int num_chain = gcd(len, num);
int len_chain = len / num_chain;
int i, j;
for(i = 0; i < num_chain; i++){
char tmp = str[i];
for(j = 0; j < len_chain-1; j++){
str[(i+j*num)%len] = str[(i+(j+1)*num)%len];
}
str[(i+j*num)%len] = tmp;
}
return retV;
}
int main(int argc, char* argv[])
{
char testStr[] = "abcdefghij";
cout << m_rotate(testStr, 4, 10) << endl;
return 0;
}