算法求解答,需要代码+注释

img

给你一个仅由 大写 英文字符组成的字符串 s 。

你可以对此字符串执行一些操作,在每一步操作中,你可以从 s 中删除 任一个 "AB" 或 "CD" 子字符串。

通过执行操作,删除所有 "AB" 和 "CD" 子串,返回可获得的最终字符串的 最小 可能长度。

注意,删除子串后,重新连接出的字符串可能会产生新的 "AB" 或 "CD" 子串。

示例 1:

输入:s = "ABFCACDB"
输出:2
解释:你可以执行下述操作:

  • 从 "ABFCACDB" 中删除子串 "AB",得到 s = "FCACDB" 。
  • 从 "FCACDB" 中删除子串 "CD",得到 s = "FCAB" 。
  • 从 "FCAB" 中删除子串 "AB",得到 s = "FC" 。
    最终字符串的长度为 2 。
    可以证明 2 是可获得的最小长度。
    示例 2:

输入:s = "ACBBD"
输出:5
解释:无法执行操作,字符串长度不变。

提示:

1 <= s.length <= 100
s 仅由大写英文字母组成

求解答

基于你提供的代码,我看到字符是 "A" 并缺栈顶元素是 "D" 时,它也会将字符压入栈中,而不是你使用的pop,可以改进用双向栈来实现,这里就不想改动

为什么只通过一半测试样例,代码如下:

class Solution:
    def minLength(self, s: str) -> int:
        stack = []
        for c in s:
            if c == 'A' or c == 'B':
                if stack and stack[-1] == 'C':
                    stack.pop()
                else:
                    stack.append(c)
            elif c == 'C' or c == 'D':
                if stack and stack[-1] == 'A':
                    stack.pop()
                else:
                    stack.append(c)
            else:
                stack.append(c)
        i = 0
        while i < len(stack) - 1:
            if (stack[i] == 'A' and stack[i+1] == 'B') or (stack[i] == 'C' and stack[i+1] == 'D'):
                stack.pop(i)
                stack.pop(i)
                i = max(0, i-1) # 回退一步
            else:
                i += 1
        res = len(stack)
        # 检查是否还有 "AB""CD" 子串
        while True:
            found = False
            for i in range(len(stack) - 1):
                if (stack[i] == 'A' and stack[i+1] == 'B') or (stack[i] == 'C' and stack[i+1] == 'D'):
                    stack.pop(i)
                    stack.pop(i)
                    res -= 2
                    found = True
                    break
            if not found:
                break
        return res