题目:请实现一个函数,把字符串中的每个空格替换成“%20”。例如输入“We are happy.”,则输出“We%20are%20happy.”。
解题思路
最直观的的做法是从头到尾扫描字符串,每次碰到空格字符的时候进行替换。由于把1个字符换成3个字符,所以必须把空格后面的字符都后移两个单位。例如字符串“We are happy.”,移动过程可由如下示意图表示:
上述解题步骤实现主要代码如下:
#include<iostream>
#include<string>
#include"stdlib.h"
using namespace std;
int main()
{
string str = "We are happy.";
int len = str.size();
cout << "原始字符串:" << str << endl;
for (int i = 0; i < len; ++i)
{
if (str[i] == 0x20)//0x20为空格的ANSI码值
{
len += 2;
str.resize(len);//每查找到一个空格,字符串长度增加2
for (int j = len - 2; j > i; --j)
{
str[j + 2] = str[j];
}
str.replace(i,3,"%20");
}
}
cout << "替换空格后的字符串:"<< str << endl;
system("pause");
return 0;
}
假设字符串的长度为n。对每个空格字符,需要移动后面O(n)个字符,因此对于含有O(n)个空格的字符串,时间复杂度为O(n^2),在面试中使用上述的解题步骤,是不能满足面试官要求的。
上述解题步骤时间主要浪费在空格后面字符串的拷贝上。因为每找到一个空格,需要拷贝后面O(n)个字符。所以可从这个角度着手改进。
我们可以从后往前拷贝,这样就可以减少拷贝的次数,每个字符至多移动一次就可以完成。思想是:
1、先扫描一次字符串,统计出空格的个数。然后在尾部分配足够的空间;2、设两个指针oriIndex和newIndex,oriIndex指向原始字符串,newIndex指向重新分配内存后的字符串;
3、从后往前拷贝,如果str[oriIndex]为空格,则在newIndex及其前面两个字符位置处填充”%20”;
4、否则将oriIndex指向的字符复制到newIndex指向的位置。
上述解题步骤实现主要代码如下:
#include<iostream>
#include<string>
#include"stdlib.h"
using namespace std;
string ReplaceSpace(string str, int length)
{
//输入非法检查
if (str.empty() && length <= 0)
return str;
int oriIndex = length;
int newIndex = 0;
int num = 0;
for (int i = 0; i < length; ++i)
{
if (str[i] == 0x20)//0x20为空格的ANSI码值
++num;
}
length += num * 2;//每查找到一个空格,字符串长度增加2
str.resize(length);
newIndex = length;
while(oriIndex >= 0 && newIndex > oriIndex)
{
if (str[oriIndex] == 0x20)//0x20为空格的ANSI码值
{
//str[newIndex--] = '0';
//str[newIndex--] = '2';
//str[newIndex--] = '%';
newIndex -= 3;
str.replace(newIndex+1, 3, "%20");
}
else
{
str[newIndex--] = str[oriIndex];
}
--oriIndex;
}
return str;
}
int main()
{
string str = "We are happy.";
int len = str.size();
cout << "原始字符串:" << str << endl;
string str2 = ReplaceSpace(str,len);
cout << "替换空格后的字符串:" << str2 << endl;
system("pause");
return 0;
}
假设字符串的长度为n。每个字符至多移动一次就可以完成,因此对于含有O(n)个空格的字符串,时间复杂度为O(n),优于前一种解题方法。
测试用例1
// 空格在句子中间
void Test1()
{
string str = "Weare happy.";
int len = str.size();
cout << "原始字符串:" << str << endl;
string str2 = ReplaceSpace(str, len);
cout << "替换空格后的字符串:" << str2 << endl;
}
测试用例2
// 空格在句子开头
void Test2()
{
string str = " Wearehappy.";
int len = str.size();
cout << "原始字符串:" << str << endl;
string str2 = ReplaceSpace(str, len);
cout << "替换空格后的字符串:" << str2 << endl;
}
测试用例3
// 空格在句子末尾
void Test3()
{
string str = "Wearehappy. ";
int len = str.size();
cout << "原始字符串:" << str << endl;
string str2 = ReplaceSpace(str, len);
cout << "替换空格后的字符串:" << str2 << endl;
}
测试用例4
// 连续有两个空格
void Test4()
{
string str = "Weare happy.";
int len = str.size();
cout << "原始字符串:" << str << endl;
string str2 = ReplaceSpace(str, len);
cout << "替换空格后的字符串:" << str2 << endl;
}
测试用例5
// 传入内容为空的字符串
void Test5()
{
string str = "";
int len = str.size();
cout << "原始字符串:" << str << endl;
string str2 = ReplaceSpace(str, len);
cout << "替换空格后的字符串:" << str2 << endl;
}
测试用例6
//传入内容为一个空格的字符串
void Test6()
{
string str = " ";
int len = str.size();
cout << "原始字符串:" << str << endl;
string str2 = ReplaceSpace(str, len);
cout << "替换空格后的字符串:" << str2 << endl;
}
测试用例7
// 传入的字符串没有空格
void Test7()
{
string str = "Wearehappy.";
int len = str.size();
cout << "原始字符串:" << str << endl;
string str2 = ReplaceSpace(str, len);
cout << "替换空格后的字符串:" << str2 << endl;
}
测试用例8
// 传入的字符串全是空格
void Test8()
{
string str = " ";
int len = str.size();
cout << "原始字符串:" << str << endl;
string str2 = ReplaceSpace(str, len);
cout << "替换空格后的字符串:" << str2 << endl;
}