2025-12-21:用特殊操作处理字符串Ⅰ。用go语言,给定一个只包含小写字母以及三种特殊符号(*、#、%)的串 s。按从左到右的顺序逐个读取字符,并维护一个

23 阅读4分钟

2025-12-21:用特殊操作处理字符串Ⅰ。用go语言,给定一个只包含小写字母以及三种特殊符号(*、#、%)的串 s。按从左到右的顺序逐个读取字符,并维护一个初始为空的字符串 result,遇到不同字符时对 result 做相应的更新:

  • 遇到小写字母:把它接到 result 的末尾;

  • 遇到 '*':如果 result 非空,则删除末尾的一个字符;

  • 遇到 '#':将当前的 result 复制一份并拼接到自身后面;

  • 遇到 '%':将 result 的字符顺序颠倒。

当所有字符处理完毕后,返回最终得到的 result。

1 <= s.length <= 20。

s 只包含小写英文字母和特殊字符 *、# 和 %。

输入: s = "a#b%*"。

输出: "ba"。

解释:

is[i]操作当前 result
0'a'添加 'a'"a"
1'#'复制 result"aa"
2'b'添加 'b'"aab"
3'%'反转 result"baa"
4'*'删除最后一个字符"ba"

因此,最终的 result 是 "ba"。

题目来自力扣3612。

📝 逐步处理过程

  1. 初始状态

    • 维护一个初始为空的字节切片 ans(对应题目描述中的字符串 result)。
  2. 处理第 1 个字符 'a' (索引 0)

    • 字符 'a' 是小写字母。
    • 操作:将 'a' 添加到 ans 的末尾。
    • 结果ans 变为 "a"
  3. 处理第 2 个字符 '#' (索引 1)

    • 字符 '#' 是特殊符号。
    • 操作:将当前的 ans 复制一份并拼接到自身后面。具体实现是 ans = append(ans, ans...),这会将 ans 切片中的所有元素追加到其末尾。
    • 结果ans"a" 变为 "aa"
  4. 处理第 3 个字符 'b' (索引 2)

    • 字符 'b' 是小写字母。
    • 操作:将 'b' 添加到 ans 的末尾。
    • 结果ans"aa" 变为 "aab"
  5. 处理第 4 个字符 '%' (索引 3)

    • 字符 '%' 是特殊符号。
    • 操作:将 ans 的字符顺序颠倒。代码中使用 slices.Reverse(ans) 实现,该函数会将切片中的元素进行原地反转。
    • 结果ans"aab" 反转为 "baa"
  6. 处理第 5 个字符 '*' (索引 4)

    • 字符 '*' 是特殊符号。
    • 操作:如果 ans 非空,则删除其末尾的一个字符。代码中通过 ans = ans[:len(ans)-1] 实现,这会创建一个不包含最后一个元素的新切片视图。
    • 结果ans"baa" 删除末尾的 'a' 后变为 "ba"
  7. 最终结果

    • 所有字符处理完毕后,将字节切片 ans 转换为字符串并返回。
    • 最终结果"ba"

⏱️ 复杂度分析

时间复杂度:O(n²)

  • 我们需要按顺序处理输入字符串 s 中的每一个字符(共 n 个操作)。
  • 大部分操作(如添加普通字符、删除末尾字符)的时间复杂度是 O(1)。
  • 但是,有两个操作会导致较高的时间复杂度:
    1. 遇到 '#' (复制)ans = append(ans, ans...) 操作需要将当前 ans 的全部内容复制一份。在最坏情况下,如果 ans 的长度是 L,这个操作的时间复杂度是 O(L)。
    2. 遇到 '%' (反转)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;
}

在这里插入图片描述