《编程之法》1.1字符串的旋转

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qibofang/article/details/51912165

题目描述:书中的字符串的旋转其实是指字符串的循环移动,如将字符串abcdef向右移动四个字符,变成cdefab


解法一:直接输出

对于字符串abcdef,输出向右移动四个字符后的目的字符串,即依次输出c,d,e,f,a,b,若想直接输出,这意味着遍历原字符串的下标0时,输出原字符串中下标为2的字符c;遍历原字符串下标1时,输出原字符串下标为3的字符d......
若字符串长为n,需向右移动m位,则原下标in与输出下标out的关系为:out = (in + n - m) % n;代码如下。时间复杂度为O(n),空间复杂度为O(0)。

#include <iostream>
using namespace std;
void DirectOutput(char str[], int m, int len){
	int i;
	for(i = 0; i < len; ++i)
		cout << str[(i + len - m) % len];
	cout << endl;
}

int main(){
	char str[110];
	int m;
	while(cin >> str >> m){
		int len = strlen(str);
		DirectOutput(str, m, len);
	}
	return 0;
}

解法二:蛮力移位  

对于字符串abcdef,建立一个函数MoveOneStep实现字符串向右循环移动一位:先保存str[len-1]到临时变量,为了避免元素覆盖问题,从后往前将s[i-1]的值赋给s[i]。这样进行m次函数调用即可。时间复杂度为O(n*m),空间复杂度为O(1)。

#include <iostream>
using namespace std;
void MoveOneStep(char str[], int len){
	int temp = str[len-1], i;
	for(i = len-1; i >= 1; --i)
		str[i] = str[i-1];
	str[i] = temp;
}

int main(){
	char str[110];
	int m;
	while(cin >> str >> m){
		int len = strlen(str);
		while(m--)
			MoveOneStep(str, len);
		int i;
		for(i = 0; i < len; ++i)
			cout << str[i];
		cout << endl;
	}
	return 0;
}

解法三:新建数组

新建一个数组,将原字符串中的元素放在输出字符串对应的位置,如字符串asdfgh需向右移动4位,则新建一个字符数组ans[],将下标为0的字符放到ans[4],下标为1的字符放到ans[5]......则原下标in与目的下标out的关系为:out = (in + m) % n。时间复杂度为O(n),空间复杂度为O(n)。

#include <iostream>
using namespace std;
void UsingArray(char str[], char ans[], int len, int m){
	int i;
	for(i = 0; i < len; i++)
		ans[(i + m) % len] = str[i];
}

int main(){
	char str[110], ans[110];
	int m;
	while(cin >> str >> m){
		int len = strlen(str);
		memset(ans, 0, sizeof(ans));
		UsingArray(str, ans, len, m);
		int i;
		for(i = 0; i < len; ++i)
			cout << ans[i];
		cout << endl;
	}
	return 0;
}

解法四:三步反转

一个规律:如将一个长度为7的字符串asdfghj向右移动4位,变为fghjasd。先对前n-m个字符所在的字符串(下标为0~n-m-1)反转,即变为dsa,再对后m个字符所在的字符串(下标为n-m~n-1的)进行反转,即变为jhgf,最后对整个字符串dsajhgf进行反转变为fghjasd。时间复杂度为O(n),空间复杂度为O(1)。
理解:若向右移动m位,那么原字符串的第n-m个字符会移到目标字符串的最后一个位置,即前n-m个字符整体移到了后面,后m个字符整体移到了前面。前两个小旋转使两个整体分段逆序,后面一个大旋转一方面使两个整体交换位置,另一方面正正得负,保证每个字符经过两次旋转后的位置不会出差错。

扫描二维码关注公众号,回复: 3789282 查看本文章
#include <iostream>
using namespace std;
void ReverseString(char str[], int start, int end){
	int temp;
	while(start < end){
		temp = str[end];
		str[end] = str[start];
		str[start] = temp;
		--end;
		++start;
	}
}

int main(){
	char str[110];
	int m;
	while(cin >> str >> m){
		int len = strlen(str);
		m = m % len;
		ReverseString(str, 0, len-m-1);
		ReverseString(str, len-m, len-1);
		ReverseString(str, 0, len-1);
		int i;
		for(i = 0; i < len; ++i)
			cout << str[i];
		cout << endl;
	}
	return 0;
}




举一反三:
题目描述:单词反转,如输入"I am a student.",输出"student. a am I"。 


解法一:在此为了简便,使用string的获得子串函数string substr(int pos = 0, int n = npos) const;,pos表示起始下标,n表示子字符串的字符个数。从后往前遍历数组,以空格为间隔分离子字符串,依次加到字符串ans中。

#include <iostream>
#include <string>
using namespace std;
int main(){
	string str, ans;
	while(getline(cin, str)){ //不能直接使用cin >> str;否则只会取第一个空格前的内容
		int i, cnt;
		for(i = str.size()-1; i >= 0; --i){//i >= 0条件针对第一个单词
			cnt = 0;
			while(i >= 0 && str[i] != ' '){
				++cnt;
				--i;
			}
			ans = ans + str.substr(i+1, cnt) + " ";
		}
		cout << ans.substr(0, str.size()) << endl;//去掉最后一个空格
	}
	return 0;
}
解法二:反转字符串两次a, 先将"I am a student."反转为".tenduts a ma I":设置两个指针指向字符串头和尾并相向移动,然后依次对换字符;b, 设置两个指针i和j,遍历一次数组,分别使他们指向字符串中某一单词的头和尾;c, 根据[i, j]区间,对每个单词进行反转,如反转ma为am,像步骤a一样头尾依次互换。实际上整个步骤需要三次遍历数组,即时间复杂度为O(n) + O(n) + O(n) = O(n),空间复杂度为O(1)。

#include <iostream>
#include <string>
using namespace std;
void Reverse(string &str, int start, int end){
	int temp;
	while(start < end){
		temp = str[start];
		str[start++] = str[end];
		str[end--] = temp;
	}
}
int main(){
	string str;
	while(getline(cin, str)){ //注意使用getline
		Reverse(str, 0, str.size()-1);
		int i = 0, j = 0;
		while(i < str.size()){
			if(i == str.size()-1 || str[i+1] == ' '){//此时i指向某一单词的最后一个位置,利用了||,若第一个条件成立,第二个就不用比较了
				Reverse(str, j, i);
				j = i + 2;//此时j跳过空格指向某一单词的第一个位置
			}
			++i;
		}
		cout << str << endl;
	}
	return 0;
}





猜你喜欢

转载自blog.csdn.net/qibofang/article/details/51912165