2025-12-21:用特殊操作处理字符串Ⅰ。用go语言,给定一个只包含小写字母以及三种特殊符号(*、#、%)的串 s。按从左到右的顺序逐个读取字符,并维护一个初始为空的字符串 result,遇到不同字符时对 result 做相应的更新:
-
遇到小写字母:把它接到 result 的末尾;
-
遇到 '*':如果 result 非空,则删除末尾的一个字符;
-
遇到 '#':将当前的 result 复制一份并拼接到自身后面;
-
遇到 '%':将 result 的字符顺序颠倒。
当所有字符处理完毕后,返回最终得到的 result。
1 <= s.length <= 20。
s 只包含小写英文字母和特殊字符 *、# 和 %。
输入: s = "a#b%*"。
输出: "ba"。
解释:
| i | s[i] | 操作 | 当前 result |
|---|---|---|---|
| 0 | 'a' | 添加 'a' | "a" |
| 1 | '#' | 复制 result | "aa" |
| 2 | 'b' | 添加 'b' | "aab" |
| 3 | '%' | 反转 result | "baa" |
| 4 | '*' | 删除最后一个字符 | "ba" |
因此,最终的 result 是 "ba"。
题目来自力扣3612。
📝 逐步处理过程
-
初始状态
- 维护一个初始为空的字节切片
ans(对应题目描述中的字符串result)。
- 维护一个初始为空的字节切片
-
处理第 1 个字符
'a'(索引 0)- 字符
'a'是小写字母。 - 操作:将
'a'添加到ans的末尾。 - 结果:
ans变为"a"。
- 字符
-
处理第 2 个字符
'#'(索引 1)- 字符
'#'是特殊符号。 - 操作:将当前的
ans复制一份并拼接到自身后面。具体实现是ans = append(ans, ans...),这会将ans切片中的所有元素追加到其末尾。 - 结果:
ans从"a"变为"aa"。
- 字符
-
处理第 3 个字符
'b'(索引 2)- 字符
'b'是小写字母。 - 操作:将
'b'添加到ans的末尾。 - 结果:
ans从"aa"变为"aab"。
- 字符
-
处理第 4 个字符
'%'(索引 3)- 字符
'%'是特殊符号。 - 操作:将
ans的字符顺序颠倒。代码中使用slices.Reverse(ans)实现,该函数会将切片中的元素进行原地反转。 - 结果:
ans从"aab"反转为"baa"。
- 字符
-
处理第 5 个字符
'*'(索引 4)- 字符
'*'是特殊符号。 - 操作:如果
ans非空,则删除其末尾的一个字符。代码中通过ans = ans[:len(ans)-1]实现,这会创建一个不包含最后一个元素的新切片视图。 - 结果:
ans从"baa"删除末尾的'a'后变为"ba"。
- 字符
-
最终结果
- 所有字符处理完毕后,将字节切片
ans转换为字符串并返回。 - 最终结果:
"ba"。
- 所有字符处理完毕后,将字节切片
⏱️ 复杂度分析
时间复杂度:O(n²)
- 我们需要按顺序处理输入字符串
s中的每一个字符(共 n 个操作)。 - 大部分操作(如添加普通字符、删除末尾字符)的时间复杂度是 O(1)。
- 但是,有两个操作会导致较高的时间复杂度:
- 遇到
'#'(复制):ans = append(ans, ans...)操作需要将当前ans的全部内容复制一份。在最坏情况下,如果ans的长度是 L,这个操作的时间复杂度是 O(L)。 - 遇到
'%'(反转):slices.Reverse(ans)操作需要遍历切片的一半进行元素交换。如果ans的长度是 L,这个操作的时间复杂度是 O(L)。
- 遇到
- 在极端情况下(例如连续的
'#'操作),ans的长度 L 可能会达到 O(n) 级别。因此,整个处理过程的最坏情况时间复杂度是 O(n²)。
空间复杂度:O(n)
- 主要的额外空间是存储结果的字节切片
ans。 - 根据题目,输入字符串长度 n ≤ 20。在最坏情况下(例如几乎全是字母和
'#'),ans的最大长度也是 O(n) 级别。 - 因此,总的额外空间复杂度是 O(n)。
Go完整代码如下:
package main
import (
"fmt"
"slices"
)
func processStr(s string) string {
ans := []byte{}
for _, c := range s {
if c == '*' {
if len(ans) > 0 {
ans = ans[:len(ans)-1]
}
} else if c == '#' {
ans = append(ans, ans...)
} else if c == '%' {
slices.Reverse(ans)
} else {
ans = append(ans, byte(c))
}
}
return string(ans)
}
func main() {
s := "a#b%*"
result := processStr(s)
fmt.Println(result)
}
Python完整代码如下:
# -*-coding:utf-8-*-
def process_str(s: str) -> str:
ans = []
for c in s:
if c == '*':
ans = ans[:-1] if ans else []
elif c == '#':
ans = ans * 2 # 直接复制
elif c == '%':
ans = ans[::-1] # 反转
else:
ans.append(c)
return ''.join(ans)
if __name__ == "__main__":
s = "a#b%*"
result = process_str(s)
print(result)
C++完整代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
std::string processStr(const std::string& s) {
std::vector<char> ans;
for (char c : s) {
if (c == '*') {
if (!ans.empty()) {
ans.pop_back();
}
} else if (c == '#') {
size_t size = ans.size();
ans.reserve(size * 2);
for (size_t i = 0; i < size; i++) {
ans.push_back(ans[i]);
}
} else if (c == '%') {
std::reverse(ans.begin(), ans.end());
} else {
ans.push_back(c);
}
}
return std::string(ans.begin(), ans.end());
}
int main() {
std::string s = "a#b%*";
std::string result = processStr(s);
std::cout << result << std::endl;
return 0;
}