返回

堆栈详解:LeetCode 394 字符串解码

前端

栈:计算机科学中的基石

引言

在计算机科学广袤的领域里,数据结构扮演着至关重要的角色。它们就像建筑中的积木,为各种复杂问题的求解奠定了坚实的基础。在众多数据结构中,栈以其独特的先入后出(LIFO)特性脱颖而出,在各种场景下大放异彩。

栈的结构与操作

想象一下现实生活中将盘子叠放在餐桌上,栈的结构与之十分相似。元素按照后进先出的顺序依次排列,就像盘子叠放一样。基于这一特性,栈提供了两个基本操作:

  • push(item) :将新元素压入栈顶,就像在盘子上方放一个新盘子。
  • pop() :移除并返回栈顶元素,就像从盘子上方取走一个盘子。

LeetCode 394:字符串解码

为了进一步理解栈在实际问题中的应用,让我们以 LeetCode 394 题:字符串解码为例。该题给出了一个经过编码的字符串,要求我们对其进行解码并返回原始字符串。编码规则如下:

  • 数字 k 表示接下来 k 个字符被括号包围的字符串将被重复 k 次。
  • 左括号 "(" 和右括号 ")" 表示一个需要被重复的子字符串。

例如,字符串 "3[a]2[bc]" 解码后变为 "aaabcbc"。

基于栈的解码算法

为了解决这个问题,我们可以巧妙地利用栈来保存待解码的子字符串。算法流程如下:

  1. 遍历输入字符串。
  2. 如果遇到数字 k,将其压入栈中。
  3. 如果遇到左括号 "(", 也将其压入栈中。
  4. 如果遇到右括号 ")", 则:
    • 弹出栈顶数字 k。
    • 弹出左括号 "(".
    • 构造子字符串 s,重复栈顶字符串 k 次。
    • 将 s 压入栈中。
  5. 重复步骤 1-4,直至遍历完整个字符串。
  6. 将栈中所有字符串依次连接起来,得到解码后的字符串。

代码实现(Python)

def decodeString(s):
    stack = []
    num = 0
    curr_str = ""
    
    for char in s:
        if char.isdigit():
            num = num * 10 + int(char)
        elif char == "[":
            stack.append(curr_str)
            stack.append(num)
            curr_str = ""
            num = 0
        elif char == "]":
            repeat_times = stack.pop()
            curr_str = stack.pop() + repeat_times * curr_str
        else:
            curr_str += char
    
    return curr_str

算法分析

该算法的时间复杂度为 O(n),其中 n 为输入字符串的长度。算法依次遍历字符串,对每个字符执行常数时间操作。

总结

栈是一种经典的数据结构,在字符串处理等诸多问题中发挥着举足轻重的作用。通过 LeetCode 394 题:字符串解码,我们深入理解了栈的结构和操作,并借助栈巧妙地解决了实际问题。掌握栈这一利器,相信你也能在算法与编程的道路上披荆斩棘,勇攀高峰。

常见问题解答

  • 栈和队列有什么区别?

栈是先入后出(LIFO)的数据结构,而队列是先进先出(FIFO)的数据结构。

  • 栈的应用场景有哪些?

栈广泛应用于函数调用、递归、语法分析和表达式求值。

  • 如何实现一个栈?

可以使用列表或数组来实现栈,并使用栈顶指针来跟踪当前的栈顶位置。

  • 栈的优点和缺点是什么?

栈的优点是操作简单、高效;缺点是只能访问栈顶元素。

  • 如何优化栈的性能?

可以使用循环队列来实现栈,从而避免数组的重新分配操作。