面试题05. 替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1:
输入:s = “We are happy.”
输出:“We%20are%20happy.”
限制:
0 <= s 的长度 <= 10000
解法一
遍历字符串,碰到空格时空格本身的位置替换为 ‘%’,并在之后插入 “20”
因为插入的过程是把字符串中的字符向后移动,所以时间复杂度为 O(n),总的时间复杂度 O(n^2),空间复杂度 O(1)
class Solution {
public:
string replaceSpace(string s) {
for(int i = 0; i < s.size(); ++i) {
if(s[i] == ' ') {
s[i] = '%';
s.insert(i+1,"20");
}
}
return s;
}
};
执行用时 :0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗 :6.3 MB, 在所有 C++ 提交中击败了100.00%的用户
解法二
开辟一个新的字符串空间,遍历原字符串,非空格字符直接附加到末尾,空格则在末尾加 “%20”
时间复杂度 O(n),空间复杂度 O(n)
class Solution {
public:
string replaceSpace(string s) {
string a;
for(auto it:s) {
if(it != ' ')
a += it;
else
a += "%20";
}
return a;
}
};
执行用时 :0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗 :6.2 MB, 在所有 C++ 提交中击败了100.00%的用户
解法三
那么有没有时间复杂度 O(n),空间复杂度 O(1) 的算法呢?
遍历字符串数空格的个数,于是新的字符串长度为原长度加上 cnt * 2,注意是乘 2 不是乘 3,因为空格本身有一个位置,每个空格再增加 2 就可以了。用两个指针 p1 p2 分别指向原来的字符串末尾以及新的字符串末尾,从后向前遍历,碰到非空格字符则复制到后面的位置,碰到空格字符则直接操作后面的指针写入 “%20”,直到遍历到字符串开头。过程中 p1 p2 的变化可以在复制时通过自减完成,精简代码长度。
class Solution {
public:
string replaceSpace(string s) {
int cnt = 0, p1 = s.size() - 1;
for(auto it:s) {
if(it == ' ') ++cnt;
}
s.resize(s.size() + cnt * 2);
int p2 = s.size() - 1;
while(p1 >= 0) {
if(s[p1] != ' ') s[p2--] = s[p1--];
else {
s[p2--] = '0';
s[p2--] = '2';
s[p2--] = '%';
p1--;
}
}
return s;
}
};
执行用时 :0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗 :6.2 MB, 在所有 C++ 提交中击败了100.00%的用户
虽然解法一的时间复杂度是 O(n^2),二和三的时间复杂度是 O(n),但提交结果的执行用时都是 0ms,不清楚是测试用例的字符串长度有限还是平台的运行时间检测有误。