左旋转字符串

        把学过的东西记下来,因为我记性不好!

一:对左旋转字符串的两种我比较中意的解法:

(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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值