概述
LC 344和541都是简单题,读清楚题目就可以。卡码网中“替换数组”这一题则提出了一种“拓展->优先处理尾部元素”的方法,大大提高了运行效率。再结合之前补数的思路,算法题中“反着来”,减少不必要的元素移动,则很有可能降低后续代码的实现难度和运行耗时。
Leetcode 344. 反转字符串
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
left = 0
right = len(s)-1
while left < right:
tmp = s[left]
s[left] = s[right]
s[right] = tmp
left += 1
right -= 1
return s
Leetcode 541. 反转字符串II
class Solution:
def reverseStr(self, s: str, k: int) -> str:
s = list(s)
for i in range(0, len(s)-1, 2*k):
if i+k < len(s):
left = i
right = i+k-1
else:
left = i
right = len(s)-1
while left < right:
tmp = s[left]
s[left] = s[right]
s[right] = tmp
left += 1
right -= 1
return "".join(s)
卡码网:替换数字
这题用Python做非常简单。
class Solution:
def replaceNumber(self,s:str)->str:
res=list(s)
for i in range(len(s)):
if res[i].isdigit():
res[i]='number'
return ''.join(res)
sol=Solution()
s=input()
result=sol.replaceNumber(s)
print(result)
但是用C++或者String可变的语言时,可以使用一种有趣的“从尾部开始”的算法来处理。如果从头开始顺序插入,每插入一个"number",后面所有的元素都需要往后挪动。但如果先算出总共要替换多少个数字,就可以提前把数组拓展到替换后的长度。指针1指向原数组的末尾,指针2指向拓展后数组的末尾。如果指针1是数字,则在指针2的位置插入number。这样插入时不会影响别的元素,从而避免插入带来的元素挪动开销。这个思路也非常重要。下面是代码随想录中给出的解法:
#include <iostream>
using namespace std;
int main() {
string s;
while (cin >> s) {
int sOldIndex = s.size() - 1;
int count = 0; // 统计数字的个数
for (int i = 0; i < s.size(); i++) {
if (s[i] >= '0' && s[i] <= '9') {
count++;
}
}
// 扩充字符串s的大小,也就是将每个数字替换成"number"之后的大小
s.resize(s.size() + count * 5);
int sNewIndex = s.size() - 1;
// 从后往前将数字替换为"number"
while (sOldIndex >= 0) {
if (s[sOldIndex] >= '0' && s[sOldIndex] <= '9') {
s[sNewIndex--] = 'r';
s[sNewIndex--] = 'e';
s[sNewIndex--] = 'b';
s[sNewIndex--] = 'm';
s[sNewIndex--] = 'u';
s[sNewIndex--] = 'n';
} else {
s[sNewIndex--] = s[sOldIndex];
}
sOldIndex--;
}
cout << s << endl;
}
}