每日一题
反转字符串中的单词
题目链接
思路(进阶)
我们首先不考虑太多限制因素,先看如何实现字符串中单词的反转
- 举个例子:我们要反转字符串“the sky is blue”中的单词,我们可以先将字符串中的每个字符反转“eht yks si eulb”,然后我们可以发现,从右到左看字符串正好就是我们想要的结果“blue is sky the”,所以再将整个字符串反转不就行了吗?
- 而具体方法我们已经在反转整个字符串,分区域反转字符串分析清楚。
接下来就是要考虑题目最恼火的限制条件:不允许多余空格的出现,即只允许单词之间出现一个空格,多余的空格须全部删除。
当然,最容易想到的还是暴力解法,即碰到字符串串首空格(字符串开头就是空格)和单词之间的重复空格,就不断将字符串的元素前移,直至覆盖多余空格,但可想而知,这样做的效率不高。
其实比较好的做法其实我们已经在移除元素中讲过,只不过上一次我们处理的是数组,而这一次处理的时字符串(实际上字符串也是数组)
- 如果不对移除元素中的代码进行改进(如下代码),那么我们实现的就是将整个字符串中的空格删除,这显然不是我们想要的结果,我们应该让每个单词之间留有一个空格
int slow = 0; for(int fast = 0; fast <= strlen(s); fast++) { if(s[fast] != ' ') s[slow++] = s[fast]; }
- 因此我们就要对上述代码进行改进:
int slow = 0; for(int fast = 0; fast <= strlen(s); fast++) { if(s[fast] != ' ') { //只要slow不位于第一个字符(不是第一个单词),就需要手动插入空格,即确保每个单词之间有一个空格 if(slow != 0) s[slow++] = ' '; //如果while仍是if,那么上述插入空格的语句就会对一个单词重复执行 //因此要用循环对每个单词进行整理 while(s[fast] != ' ' && s[fast] != '\0') s[slow++] = s[fast++]; } }
实现代码
void Part_reverseWords(char* s, int left, int right) //反转指定区域的字符串
{
while (left <= right)
{
char temp = s[left];
s[left] = s[right];
s[right] = temp;
left++;
right--;
}
}
void ReplaceSpaces(char *s) //删除多余空格
{
int slow = 0;
for(int fast = 0; fast < strlen(s); fast++)
{
if(s[fast] != ' ')
{
//只要slow不位于第一个字符(不是第一个单词),就需要手动插入空格,即确保每个单词之间有一个空格
if(slow != 0)
s[slow++] = ' ';
//如果while仍是if,那么上述插入空格的语句就会对一个单词重复执行
//因此要用循环对每个单词进行整理
while(s[fast] != ' ' && s[fast] != '\0')
s[slow++] = s[fast++];
}
}
s[slow ] = '\0'; //在新的字符串末尾添加结束符
}
char* reverseWords(char* s) {
ReplaceSpaces(s);
int i = 0;
//对每个单词进行反转
for (int j = i + 1; j <= strlen(s); j++)
{
if (s[j] == ' ' || j == strlen(s))
{
Part_reverseWords(s, i, j - 1);
i = j + 1;
}
}
//对整个字符串反转
Part_reverseWords(s,0,strlen(s) - 1);
return s;
}