栈(5) --hot 100 in leetcode
有效的括号
算法概述
本题要求为判断输入的括号组成的字符串是否有效。所有字符遍历,一半字符串入栈, ***另外一半与此时栈内的进行匹配 ***。
- 时间复杂度为O(n)
- 空间复杂度为O(n+∑):栈(原字符)和哈希表(字符集)
JAVA
1 | class Solution { |
重要实例方法及属性(JAVA)
再总结一下:Deque<Character> stack = new LinkedList<Character>();
:JAVA因为stack较老的原因,一般使用双向队列实现栈Deque.isEmpty()
:是否为空Deque.peek()
:栈顶Deque.pop()
:弹出Deque.push()
:压入
C++
1 | // 可用stack |
重要实例方法及属性(C++)
stack.empty()
:是否为空stack.top()
:栈顶stack.pop()
:弹出栈顶stack.push()
:压入
注意
入栈一半元素,与之后的元素匹配,利用的是 括号分左右 的特性以及 二分后彼此匹配 。
要记得使用 哈希表存储字符集 ,这里使用栈的主要原因是 栈的后进先出 与括号的规律一样。
最小栈
算法概述
本题要求为设计一个能在常数时间内检索到最小元素的栈。采用一个 辅助栈 存储当前实例内状态的最小值。
- 时间复杂度为O(1):常数时间查找
- 空间复杂度为O(n):辅助栈
JAVA
1 | class MinStack { |
C++
1 | // 与之类似 |
注意
辅助栈的思路类似于 迭代 ,因为入栈时从第一个元素开始的,所以最小值永远可以与当前栈顶元素进行比较得到,所以 能不断重复此过程 。除了保存每次入栈后栈内最小值,也可以通过更巧妙的方法,避免那么多次的入栈与出栈。
比如,在入栈时加入判断:
1 | if (minStack.isEmpty() || x <= minStack.peek()) { |
只有 比栈顶元素小的时候 才入栈,同时
1 | if (popped == minStack.peek()) { |
出栈时判断栈内当前最小值(辅助栈栈顶)是不是当前出栈的元素再决定对不对辅助栈进行操作。
这样做避免了在 升序入栈 的时候重复入栈的操作,因为 升序入栈时最小值就是第一个元素 ,无需考虑之后的元素。
字符串解码
算法概述
本题要求为对给出的数字+’[]’形式重复前缀数字次数的’[]’内的字符串/字符。使用一个栈便可实现。但是处理字符串等等操作比较复杂。
- 时间复杂度为O(n):n为解码后的字符串长度
- 空间复杂度为O(n):
JAVA
1 | class Solution { |
重要实例方法及属性(JAVA)
Character.isDigit()
:静态方法判断数字LinkedList.addLast()
:确定添加至末尾Character.isLetter()
:判断是否为字符LinkedList.removeLast()
:移除末尾元素LinkedList.peekLast()
:返回末尾元素String.valueOf()
:将各种数据类型转换为String
Collections.reverse()
:翻转数据Integer.parseInt()
:将字符串转换为数字
C++
1 | // api很不一样,实现思路一样 |
重要实例方法及属性(C++)
isdigit()
:判断数字isalpha()
:判断字符reverse(begin(),end())
:面向STL的翻转,有迭代器的重载
注意
实现底层较为复杂,需要 反复训练直至完全掌握 。
每日温度
算法概述
本题要求为对于给出温度数组,返回相同索引下记录当天需要多少天温度继续升高的数组(隔多久值变大)。可以使用 单调栈 ,也就是在遍历的同时,只保存 未找到后续更大值的温度索引 。
- 时间复杂度为O(n):只需遍历一次
- 空间复杂度为O(n):最大只需一个和原数组长度相当的栈
JAVA
1 | class Solution { |
C++
1 | // 一样的 |
注意
这道题的关键是 对数据做了预处理 ,也就是 使用下标而不是数据本身 来进行统计,这不管对于哪个数据结构都应该有类似的思维,也就是 通过一层预处理使数据结构特性能够被利用 。
!stack.isEmpty()
:要记得判断栈空的边界情况int[] ans = new int[length];
:初始定义一个数组来存储答案,与预处理的步骤相适配while (!stack.isEmpty() && temperature > temperatures[stack.peek()])
:要用while
,因为可能有多个栈中元素同时比当前元素小stack.push(i);
:当前元素入栈和之前的while
无关, 每个元素都要入栈一次
柱状图中最大的矩形
算法概述
本题要求为对给出的表示柱形高度的数组,找到其中能够勾勒出来的最大矩形。也就是说核心还是相邻的柱形的高度 比较问题 ,和上一题一样,应该使用 单调栈 。可以使用两次栈来得到左右边界,也可以通过 哨兵 优化为一次栈的操作。
- 时间复杂度为O(n)
- 空间复杂度为O(n)
JAVA
1 | class Solution { |
C++
1 | // 一样 |
注意
这道题本身是求两个边界索引,相当于 两个每日温度问题 ,但通过 使用哨兵填充右边界值 ,将栈操作精简化。
while (!mono_stack.isEmpty() && heights[mono_stack.peek()] >= heights[i])
:外部循环是用来找有边界值的,栈中会一直按照索引存放升序排列的元素,直至遍历到比栈顶小的元素right[mono_stack.peek()] = i;
:在遇到比栈顶小的元素时,说明找到了栈顶的右边界while (!mono_stack.isEmpty() && heights[mono_stack.peek()] >= heights[i])
:要用while
对此时栈中所有升序存储的元素设置右边界,当前值可能 不止只是当前栈顶的右边界left[i] = (mono_stack.isEmpty() ? -1 : mono_stack.peek());
:左边界一直取的都是栈顶,因为经过上面的while
,栈顶绝对比当前值小,或者为-1ans = Math.max(ans, (right[i] - left[i] - 1) * heights[i]);
:面积计算公式需要自己推导
解法的核心是 通过栈统一处理升序元素的右边界 ,然后确保左边界更新时只剩下 栈顶永远比当前元素小 的情况。也就是说栈在此的功能,就是 分离一部分有规律的元素 并使得它们能够被 统一处理 。
- Title: 栈(5) --hot 100 in leetcode
- Author: tobegold574
- Created at : 2024-11-25 21:37:49
- Updated at : 2024-12-02 13:32:52
- Link: https://tobegold574.me/2024/11/25/栈-5-hot-100-in-leetcode/
- License: This work is licensed under CC BY-NC-SA 4.0.