1. 简单四则运算解析器
背景
栈在四则运算表达式求值中的应用,尤其是处理中缀表达式时,可以帮助解决运算符优先级、括号嵌套等问题。栈通过记录运算符和操作数,确保按正确的顺序执行运算。
解析流程
- 运算符优先级 栈帮助处理不同运算符的优先级,确保高优先级的运算符优先计算。通过比较栈顶运算符和当前运算符的优先级来决定是否需要进行计算。
- 括号的匹配 在遇到左括号
(时压栈,遇到右括号)时弹栈并计算括号内的表达式。栈帮助我们确保括号内的表达式先于外部表达式被计算。 - 操作数的处理 数字直接压入操作数栈,运算符控制计算顺序。最终操作数栈中的数字即为最终结果。
- 整数除法与负号处理 在进行除法时需要特别注意整数部分的计算,以及负号的处理。
栈的操作
- 压栈:将数字或运算符压入栈中。
- 弹栈:根据运算符或括号要求,从栈中弹出元素。
- 栈顶比较:与栈顶运算符优先级进行比较,决定是否计算。
优点
- 简化运算逻辑:栈能够高效管理运算符优先级和括号匹配,避免复杂的循环和递归。
- 时间复杂度:通常情况下,栈的使用将时间复杂度控制在 O(n)。
2. 最大乘积问题
问题描述
给定一个由 '('、')'、'{'、'}'、'['、']' 组成的字符串,判断字符串中的括号是否有效。有效的括号必须满足以下条件:
- 左括号必须与相应的右括号匹配。
- 每个右括号都必须有一个对应的左括号。
- 括号的顺序必须正确。
栈的应用
栈在括号匹配问题中发挥了重要作用。我们通过栈来追踪每个左括号,遇到右括号时,栈顶的左括号与其匹配。
解析过程
-
遇到左括号时:将其压入栈中。
-
遇到右括号时:
- 检查栈是否为空。如果为空,说明没有匹配的左括号,返回
false。 - 弹出栈顶元素,判断栈顶元素是否与当前右括号匹配。若匹配,则继续;若不匹配,返回
false。
- 检查栈是否为空。如果为空,说明没有匹配的左括号,返回
-
字符串遍历结束时:如果栈为空,说明所有的左括号都已经匹配完毕,返回
true;否则,返回false。
栈的操作
- 压栈:每遇到左括号时,将其压入栈。
- 弹栈并匹配:遇到右括号时,弹出栈顶元素进行匹配。
- 栈为空:若栈为空,说明没有匹配的括号,返回
false。
时间复杂度
由于每个括号只会被压入栈一次,且每个括号也只会被弹出一次,所以时间复杂度为 O(n),其中 n 是字符串的长度。
优点
- 高效性:栈能够在一次遍历中完成括号匹配的工作,时间复杂度较低。
- 简洁性:利用栈能够很直观地解决括号匹配的问题,代码简洁易懂。
3. 最大区间乘积问题
问题描述
给定一个列表 T 表示每日温度。对于每一天,查找离它最近的未来某一天的温度大于它的天数。如果没有这样的未来天数,则返回 0。例如:对于温度列表 [73, 74, 75, 71, 69, 72, 76, 73],返回结果为 [1, 1, 4, 2, 1, 1, 0, 0]。
栈的应用
栈在此问题中用于保持温度列表中尚未找到更高温度的天数。栈中的每个元素是一个索引,栈的目的是通过当前的温度和栈中元素的温度进行比较,从而找到下一个更高温度的天数。
解析过程
-
遍历温度列表:
- 对于每一天,若当前温度大于栈顶元素对应的温度,则弹出栈顶元素,并计算这天和弹出的天数之间的差值。
- 将当前天数的索引压入栈中。
-
栈的作用:
- 栈保存的是一个暂时没有找到更高温度的天数索引。
- 当我们遍历到一个温度较高的天数时,栈中的索引会被弹出,计算当前天和较低温度天数的天数差。
-
最终结果:若栈中还有元素,则意味着这些天没有找到更高温度,对应位置的结果为
0。
时间复杂度
遍历列表一次,每个元素最多进栈一次和出栈一次,所以时间复杂度为 O(n),其中 n 是温度列表的长度。
优点
- 空间效率:通过栈的使用,能够有效地减少冗余的计算。
- 时间效率:在一次遍历中解决问题,避免了多重嵌套循环,时间复杂度 O(n) 是非常高效的。