请实现一个函数,把字符串中的每个空格替换成“%20”。例如输入“We are happy.",则输出”We%20are%20happy."
分析:在空间复杂度尽可能低的情况下,不允许开辟一个新的数组来存放替换空格后的字符串。如果从前往后替换字符串,那么保存在空格后面的字符串肯定会被覆盖。假设字符串的长度为n。对每个空格字符,需要移动后面O(n)个字符,因此对含有O(n)个空格字符的字符串而言总的时间复杂度是O(n^2),明显不可取。
思路:我们考虑从后往前进行替换,时间复杂度降为O(n)。
(1)首先遍历一遍字符串,找出字符串的长度以及其中的空格数
(2)根据原字符串的长度和空格数求出最后新的字符串的长度
(3)设置两个指针分别指向原字符串和新字符串的末尾位置
(4)如果原字符串的指针指向的内容不空,则将内容赋值给新指针指向的位置;否则从新指针开始向前赋值“02%”
(5)直到两个指针相等时表明字符串中的所有空格已经替换完毕
C++代码:
- #include "stdafx.h"
- #include <iostream>
- using namespace std;
- //将字符串str中的空格替换为"%20"
- void ReplaceBlank(char *str)
- {
- int nOldLength = strlen(str);//计算字符串的长度
- //遍历字符串,求出其中空格的个数
- int nCountOfBlank = 0;
- char *p = str;
- while (*p != '\0')
- {
- if (*p == ' ')
- {
- ++nCountOfBlank;
- }
- ++p;
- }
- int nNewLength = nOldLength + nCountOfBlank * 2;//新字符串的长度
- int nOldIndex = nOldLength - 1;
- int nNewIndex = nNewLength - 1;
- while(nOldIndex != nNewIndex)
- {
- if (str[nOldIndex] != ' ')
- {
- str[nNewIndex--] = str[nOldIndex];
- }
- else
- {
- str[nNewIndex--] = '0';
- str[nNewIndex--] = '2';
- str[nNewIndex--] = '%';
- }
- --nOldIndex;
- }
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- char str1[50] = "We are happy.";
- ReplaceBlank(str1);
- cout << str1 << endl;
- char str2[50] = " We are happy. ";
- ReplaceBlank(str2);
- cout << str2 << endl;
- char str3[50] = "";
- ReplaceBlank(str3);
- cout << str3 << endl;
- char str4[50] = " ";
- ReplaceBlank(str4);
- cout << str4 << endl;
- system("pause");
- return 0;
- }
二、清除空格
请事先一个函数,把字符串中的每个空格清除。例如输入“We are happy.",则输出”Wearehappy."
分析:较为简单,直接从头到尾进行清除。
(1)设置两个指针p1和p2初始状态都指向字符串的首字符
(2)若p2指向的元素不空,则将p2指向的内容赋给p1,然后都指向下一个元素;否则为空格,则p2指向下一元素。
(3)直到p2指向字符串末尾“\0”时清除空格结束。
C++代码:
- #include "stdafx.h"
- #include <iostream>
- using namespace std;
- //清除字符串str中的空格,从前往后遍历
- void DeleteBlank(char *str)
- {
- if (str == NULL)
- {
- return;
- }
- char *p1 = str;
- char *p2 = str;
- while (*p1 != '\0')//注意此处应该是p1,不是p2,因为'\0'仍然需要赋给p1
- {
- if (*p2 != ' ')
- {
- *(p1++) = *(p2++);
- }
- else
- {
- p2++;
- }
- }
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- char str1[50] = "We are happy.";
- DeleteBlank(str1);
- cout << str1 << endl;
- char str2[50] = " We are happy. ";
- DeleteBlank(str2);
- cout << str2 << endl;
- char str3[50] = "";
- DeleteBlank(str3);
- cout << str3 << endl;
- char str4[50] = " ";
- DeleteBlank(str4);
- cout << str4 << endl;
- system("pause");
- return 0;
- }
三、清除多余空格
给定字符串,删除开始和结尾处的空格,并将中间的多个连续的空格合并成一个。例如输入“ We are happy. ”,则输出“We are happy.”
分析:同样是从前往后遍历,但需要定义一个bool变量标记是否保存一个空格。初始化时被设置为fasle,这样开始阶段的空格都不会被保存,当碰到一个非空格字符时,保存该字符,然后将标记设置为true,表示会保存字符串中的第一个空格。经过上述几步操作,可以保证字符串结尾要么是空字符,要么是非空格字符。如果是空格字符,则将其设置为"\0",如果不为空格字符,则在其后面加上"\0"。
C++代码:
- #include "stdafx.h"
- #include <iostream>
- using namespace std;
- //清除字符串str中多余的空格,从前往后遍历
- void DeleteRedundantBlank(char *str)
- {
- if (str == NULL)
- {
- return;
- }
- char *p1 = str;
- char *p2 = str;
- bool keepBlank = false;//记录空格是否保存
- while (*p1 != '\0')//注意此处应该是p1,不是p2,因为'\0'仍然需要赋给p1
- {
- if (*p2 != ' ')
- {
- *(p1++) = *(p2++);
- keepBlank = true;
- }
- else
- {
- if (keepBlank)
- {
- *(p1++) = *(p2++);
- keepBlank = false;
- }
- else
- {
- p2++;
- }
- }
- }
- int nlen = strlen(str);
- if (str[nlen - 1] == ' ')
- {
- str[nlen - 1] = '\0';
- }
- nlen = strlen(str);
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- char str1[50] = "We are happy.";
- DeleteRedundantBlank(str1);
- cout << str1 << endl;
- cout << strlen(str1) << endl;
- char str2[50] = " We are happy. ";
- DeleteRedundantBlank(str2);
- cout << str2 << endl;
- cout << strlen(str2) << endl;
- char str3[50] = "";
- DeleteRedundantBlank(str3);
- cout << str3 << endl;
- char str4[50] = " ";
- DeleteRedundantBlank(str4);
- cout << str4 << endl;
- system("pause");
- return 0;
- }