1 题目:
请实现一个函数,把字符串中的每个空格替换成"%20"。例如输入“We are happy.”
,则输出“We%20are%20happy.”
。
2 题解
2.1 暴力解法 O(n2)
依次扫描字符串,遇到空格,则将后面字符向后移动两个单位,并从当前位置开始添加字符%20
。
假设字符串长度为 n,对每个空格字符,需要移动后面 O(n) 个字符,因此对于含有 O(n) 个空格字符的字符串而言,总的时间效率是 O(n2)。
2.2 优雅解法 O(n)
我们换一种思路,把从前向后替换 改成 从后向前替换。
首先遍历一次字符串,统计字符串中空格的总数,以此计算替换之后的新字符串的长度。每替换一个空格,长度加 2,因此新字符串的长度等于原始长度加上 2 乘以空格总数。
首先准备两个指针,P1 指向原始字符串的末尾,P2 指向新字符串的末尾。接着向前移动 P1 ,逐个把它指向的字符复制到 P2 指向的位置,直到碰到第一个空格为止。
碰到空格后,P1 向前移动一格,P2 向前移动 3 格并插入%20
。直到P1 P2指向同一位置,替换完毕。
上面这种方法,只移动了一次,所以时间复杂度是O(n)。
3 代码
C++
#include <iostream>
using namespace std;
class Solution
{
public:
// length 为字符数组 string 的总容量
void ReplaceBlank(char str[], int length)
{
if (str == nullptr && length <= 0)
return;
/*originalLength 为字符串str的实际长度*/
int originalLength = 0;
int numberOfBlank = 0; // 空格数目
int i = 0;
while (str[i] != '\0') // 计算实际长度,空格数
{
++originalLength;
if (str[i] == ' ')
++numberOfBlank;
++i;
}
cout << originalLength << endl;
/*newLength 为把空格替换成“%20”之后的长度*/
int newLength = originalLength + numberOfBlank * 2;
if (newLength > length)
return;
int indexOfOriginal = originalLength; // 指向实际长度末尾
int indexOfNew = newLength; // 指向新长度的末尾
while (indexOfOriginal >= 0 && indexOfNew > indexOfOriginal)
{
if (str[indexOfOriginal] == ' ') // 若指针1扫描到空格,则依次向前添加字符
{
str[indexOfNew--] = '0';
str[indexOfNew--] = '2';
str[indexOfNew--] = '%';
}
else // 若指针1没有扫描到空格
{
// 则移动位置
str[indexOfNew--] = str[indexOfOriginal];
}
--indexOfOriginal;
}
}
// 暴力,O(n2)
void replaceBlankForce(char str[], int length)
{
if (str == nullptr && length <= 0)
return;
int originalLength = 0;
int i = 0;
while (str[i] != '\0') // 计算实际长度
{
++originalLength;
++i;
}
i = 0;
int newLength = originalLength;
while (str[i] != '\0')
{
if (str[i] == ' ') // 若碰到一次空格,则后面就要移动一次位置
{
newLength += 2;
for (int j = newLength; j > i; j--)
{
str[j] = str[j-2];
}
str[i++] = '%';
str[i++] = '2';
str[i++] = '0';
}
else i++;
}
}
};
int main()
{
const int length = 100;
char str[length] = "hello world";
Solution solu;
solu.ReplaceBlank(str, length);
cout << str << endl;
cin.get();
return 0;
}
Python
class Solution:
# 使用append依次遍历即可替换 O(n)
def replaceSpaceByAppend(self, s):
string = list(s)
stringReplace = []
for item in string:
if item == ' ':
stringReplace.append('%')
stringReplace.append('2')
stringReplace.append('0')
else:
stringReplace.append(item)
return "".join(stringReplace)
# 字符串拼接
def replaceSpaceByStr(self, s):
temp = ''
if type(s) != str: return "Wrong! You should input a str!"
for c in s:
if c == ' ':
temp += '%20'
else:
temp += c
return temp
def replaceSpaceByBultin(self, s):
if type(s) != str:
return
return s.replace(' ', '%20')
# 书中方法,python实现起来麻烦且慢,不推荐
def replaceSpace(self, s):
if not isinstance(s,str) or len(s) <= 0 or s == None:
return ""
spaceNum = 0
for i in s:
if i == " ":
spaceNum += 1
newStrLen = len(s) + spaceNum * 2
newStr = newStrLen * [None]
indexOfOriginal, indexOfNew = len(s) - 1, newStrLen - 1
while indexOfNew >= 0 and indexOfNew >= indexOfOriginal:
if s[indexOfOriginal] == ' ':
newStr[indexOfNew-2:indexOfNew+1] = ['%', '2', '0']
indexOfNew -= 3
indexOfOriginal -= 1
else:
newStr[indexOfNew] = s[indexOfOriginal]
indexOfNew -= 1
indexOfOriginal -= 1
return "".join(newStr)
s = 'Hello World!'
a = 123
solu = Solution()
print(solu.replaceBlank(s))