LeetCode 剑指 Offer 05. 替换空格
题目描述
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1:
输入:s = "We are happy."
输出:"We%20are%20happy."
限制:
0 <= s 的长度 <= 10000
方法一:遍历添加
在 Python 和 Java 等语言中,字符串都被设计成「不可变」的类型,即无法直接修改字符串的某一位字符,需要新建一个字符串实现。
解决思路:遍历列表 s 中的每个字符 c :
- 当 c 为空格时:向 res 中添加字符串 “%20” ;
- 当 c 不为空格时:向 res 中添加字符 c ;
代码
class Solution:
def replaceSpace(self, s: str) -> str:
res = []
for c in s:
if c == ' ':res.append("%20")
else:
res.append(c)
return "".join(res) #将序列中的元素按""连接生成一个新的字符串
结果and总结
- 运行时间:36ms 内存消耗:13.5MB
- 时间复杂度 O(N):遍历使用 O(N),每轮添加(修改)字符操作使用 O(1)
- 空间复杂度 O(N): Python 新建的 list 和 Java 新建的 StringBuilder 都使用了线性大小的额外空间。
- 注意返回的时候要写成
return "".join(res)
,如果直接写成return res
,会出现如图的错误:
方法二:python3直接用replace()
函数
代码
class Solution:
def replaceSpace(self, s: str) -> str:
return s.replace(" ", "%20")
结果and总结
- 运行时间:36ms 内存消耗:13.3MB
- 这种方法并没有考验到算法能力,面试的时候不要使用
方法三:原地修改(C++)
在 C++ 语言中, string 被设计成「可变」的类型,因此可以在不新建字符串的情况下实现原地修改。
解决思路:
- 统计空格数量:遍历 s ,遇空格则 count++ ;
- 修改 s 长度:添加完 “%20” 后的字符串长度应为
len + 2 * count
; - 倒序遍历修改:如图所示,i 指向原字符串尾部元素, j 指向新字符串尾部元素;当 i = j 时跳出(代表左方已没有空格,无需继续遍历):
- 当 s[i] 不为空格时:执行 s[j] = s[i] ;
- 当 s[i] 为空格时:将字符串闭区间 [j-2, j] 的元素修改为 “%20” ;由于修改了 3 个元素,因此需要 j -= 2 ;
代码
class Solution {
public:
string replaceSpace(string s) {
int count = 0, len = s.size();
for (char c : s) {
if(c == ' ')
count++;
}
s.resize(len + 2 * count);
for(int i = len -1, j = s.size() - 1; i < j; i--, j--){
if (s[i] != ' ')
s[j] = s[i];
else if(s[i] == ' '){
s[j-2] = '%';
s[j-1] = '2';
s[j] = '0';
j -= 2;
}
}
return s;
}
};
结果and总结
- 运行时间:4ms 内存消耗:6.6MB
- 时间复杂度 O(N) : 遍历统计、遍历修改皆使用 O(N) 时间。
- 空间复杂度 O(1) : 由于是原地扩展 s 长度,因此使用 O(1) 额外空间。
小结
- 虽然Python语言看起来很简单,但和C++比起来运行时间和内存消耗还是很大,果然Python底层还是C或者Java写的