字符串循环左移(右移)的2种算法(附图解析)

问题描述:

给定一个字符串s[0…n-1],要求将s的前k个字符移动到字符串s的尾部。
举个栗子:将字符串“HelloWorld”的前5个字符移动到字符串的尾部,即要得到的新串为:“WorldHello”;即将字符串的循环左移k位

顺便bb:循环左移k位,等价于循环右移n-k位(n位字符串长度)

暴力法

思路:不是循环左移k位吗,那么就简单粗暴的一位一位的移动就是了。将首位暂存,后面的依次前移,最后将首位放到最后,就循环左移了1位,调用k次这个方法,就循环左移了k位。

C++代码:

//循环左移一位,s位字符数组,n为长度
void OneLeftMove(char *s, int n) {
	char char0 = s[0];//暂存第一个字符
	for (int i = 1; i < n; i++) {
		s[i - 1] = s[i];
	}
	s[n - 1] = char0;
}
//调用k次左移,即循环左移k位
void LeftMovek(char *s, int k,int n) {
	for (int i = 0; i < k; i++) {
		OneLeftMove(s, n);
	}
}

暴力法时间复杂度:O(kN),空间复杂度:O(1)

利用三次翻转巧妙实现

思路:
例如:字符串有XY组成,要想变成YX
即:XY->YX
(X’Y’)’=YX ‘表示将x翻转
栗子:abcd’=dcba efgh’=hgfe
(abcd’efgh’)’=(dcbahgfe)’=efghabcd
理解:这个也不难理解,如图所示:
在这里插入图片描述
在这里插入图片描述
C++代码:

void ReverseString(char *s, int from, int to) {
	while (from < to) {
		char t = s[from];
		s[from++] = s[to];
		s[to--] = t;
	}
}
//三次翻转实现,实现将串长度为n的串s,循环左移k位
void LeftRotateString(char* s, int n, int k) {
	k %= n;//求模,例如字符串共5位,要右移7位,就和移动2位是一样,取模防止越界
	ReverseString(s, 0, k - 1);
	ReverseString(s, k, n - 1);
	ReverseString(s, 0, n - 1);
}

代码解析:
翻转算法很简单,从两边到中间一次交换就是了。
下面的三次翻转,就是分别将前半部分,后半部分,和整体在进行翻转就是了,整体非常简单。
注意可以k %= n;取模防止越界

该算法时间复杂度:O(n),空间复杂度:O(1)

##结束语
相互学习,共同进步。若有错误,希望各位看官批评指正!

发布了2 篇原创文章 · 获赞 2 · 访问量 52

猜你喜欢

转载自blog.csdn.net/K__Ming/article/details/105278412