剑指offer面试题(5)——替换空格

        题目:请实现一个函数,把字符串中的每个空格替换成“%20”。例如输入“We are happy.”,则输出“We%20are%20happy.”。

解题思路

        最直观的的做法是从头到尾扫描字符串,每次碰到空格字符的时候进行替换。由于把1个字符换成3个字符,所以必须把空格后面的字符都后移两个单位。例如字符串“We are happy.”,移动过程可由如下示意图表示:

剑指offer面试题(5)——替换空格_第1张图片

        上述解题步骤实现主要代码如下:

#include
#include
#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和newIndexoriIndex指向原始字符串,newIndex指向重新分配内存后的字符串;
        3、从后往前拷贝,如果str[oriIndex]为空格,则newIndex及其前面两个字符位置处填充”%20”;
        4、否则将oriIndex指向的字符复制到newIndex指向的位置

        上述解题步骤实现主要代码如下:

#include
#include
#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;
}

你可能感兴趣的:(剑指offer)