栈
栈
abant2
世界上最菜的arcem
展开
-
leetcode 2197 用栈模拟质数合并
此题并不需要什么算法,模拟即可。但是复杂的模拟方式可能带来很长很丑的代码。此题说了,任意顺序合并都可以得到相同的结果,所以此题可以用单调栈的思想解决,从左边开始,每次弹出两个,不断合并,如果右边可以合并完成,一定会反馈给左边,还是很玄妙的。class Solution {public: int gcd(int a, int b) { if(b == 0)return a; return gcd(b, a%b); } vector<.原创 2022-03-12 17:18:15 · 7766 阅读 · 0 评论 -
leetcode 155 最小栈
这个题看着第一个想法是栈加优先队列,存两个数据结构(是不是没救了)其实此题非常简单,咱们只要让在栈中存一个pair,让栈中的每个元素维护最小值即可。class MinStack {typedef pair<int, int> P;public: stack<P> s; /** initialize your data structure here. */ MinStack() { } void push(int val) .原创 2021-07-29 15:04:39 · 64 阅读 · 0 评论 -
二叉树的迭代遍历
二叉树的迭代遍历其实蛮简单的,核心就是栈。中序和后序遍历,需要考虑根节点是否看过,需要在栈中存pair,判断是否遍历过。对于前序遍历则不需要。三种遍历方式代码都蛮像的。前序:class Solution {public: vector<int> preorderTraversal(TreeNode* root) { stack<TreeNode*> s; vector<int> ans; if(!root)r原创 2021-07-24 20:47:46 · 83 阅读 · 0 评论 -
leetcode 32 dp+栈+两次遍历 多种解法
这个题真的是一道好题,看起来如此简单,实际却如此复杂(应该说包含了很多知识)。解法一:dp此题的dp定义是比较大胆的(其实也挺常规的),就是以当前字符结尾的最长有效长度。说他大胆是因为这样定义的话,所有以左括号结尾的dp值都为0.状态转移:如果当前字符是右括号,并且上一个是左括号,那么比较简单,dp[i]=dp[i−2]dp[i] = dp[i-2]dp[i]=dp[i−2]接下来就是核心:现在只剩一种情况,就是当前字符是右括号,上一个也是右括号。此时咱们看dp[i−1]dp[i-1]dp[i−1.原创 2021-07-10 23:56:32 · 173 阅读 · 1 评论 -
leetcode 772 基本计算器3 双栈解析表达式 单调栈
此题是比较难的一个题,不能简单的用递归来做。假设我们已经能把数字分离出来,并且解决了其他无关细节。此时我们要考虑,如何处理括号和运算优先级。此题最强的一点是,当你看到一个符号时,你就可以决定上一个运算是否可以立即执行。比如,你看到了+,那么上一步的乘法就可以立即执行。这里,我们要将括号分开处理,因为这不是一个操作,我们不希望他提前执行。通过上一步的处理之后,所有符号应该都是优先级递增的,所以都可以被逆序执行。这是一个很隐晦的单调栈。通过上述分析,我们可以把步骤分解为以下的贪心思想:遇见空格:跳过.原创 2021-07-05 00:31:04 · 465 阅读 · 0 评论 -
leetcode 150 栈简单表达式问题
此题没什么难度,主要是对c++语法更熟悉了下,一个是isdigit不能判断字符串,还有就是要注意符号的判断,还有字符串和数之间的相互转化。#include <ctype.h>class Solution {public: int evalRPN(vector<string>& tokens) { vector<int> s; for(auto t: tokens) { if(is原创 2021-03-20 12:55:01 · 54 阅读 · 0 评论 -
leetcode 769, 768 最多能完成排序的块 单调栈建模
首先是769,这个题是很简单的,只要看最大元素和索引关系即可。class Solution: def maxChunksToSorted(self, arr: List[int]) -> int: result, bad = 0, -1 for i in range(len(arr)): bad = max(bad, arr[i]) if bad <= i: result +原创 2020-11-14 18:01:42 · 187 阅读 · 0 评论 -
leetcode 402 移掉K位数字 单调栈
去除k位数字,使剩下的数字最小(字典序最小)。做题多了还是有好处的,这和昨天的分块问题是一样的,都可以用单调栈解决。如果后面有比前面小的,那前面的就应该删去。还有要注意的就是栈为空时不能push0进栈,此处用字符串模拟栈,各种操作都是O(1)的。用list也可,但会麻烦些。class Solution: def removeKdigits(self, num: str, k: int) -> str: stack = "" for idx, c in enum原创 2020-11-15 15:31:16 · 65 阅读 · 0 评论 -
leetcode 767 堆+贪心两种做法
解法一:堆这个做法真的很秒,把所有字符及其数量放入堆中,然后每次排出最大的两个元素,这样就不会有重复,真的惊了,太强的做法!这次用了python实现堆,学会了__lt__定义比较函数,python还是很香。from queue import PriorityQueueclass Solution: def reorganizeString(self, S: str) -> str: class node: def __init__(self, c,原创 2020-11-30 16:52:15 · 203 阅读 · 0 评论 -
leetcode 316 321 单调栈强化
之前做过402,也是单调栈,那个题可以选择去掉k个数字后的最小数,这种思想其实和本次的两个题是一样的,就是贪心的去掉前面较大的数字即可。而leetcode 768则是稍复杂的单调栈,pop的元素不是移除,而是合并,保留的是最大值,这个题是很值得回味的。回到316,这个题是一道难度超过medium的题,代码非常简单,思想不是那么容易。首先,与402类似,但咱们只能排出还能放进去的元素,所以要存个数组,放剩余的元素个数。第二个问题是,如果元素已在栈中,还要不要处理?答案很简单,不要。因为如果元素在栈中却没有被原创 2020-12-02 22:30:52 · 76 阅读 · 0 评论 -
leetcode 376 贪心 dp LIS
解法一:普通dp一看到子序列就想到dp,和LIS一样的套路,存以当前元素结尾的子序列长度。由于不知道前面序列的状态,需要再存一个status数组,看期待大的还是小的元素,代码如下:class Solution: def wiggleMaxLength(self, nums: List[int]) -> int: # 子序列问题 dp 设dp[i]是以他结尾一个元素,遍历之前的 dp = [1 for _ in range(len(nums))]原创 2020-12-14 21:28:49 · 87 阅读 · 0 评论 -
leetcode 85 暴力+dp+单调栈 无敌题目
解法一:中等暴力提前预存好每个竖的连续区间是否全为1,并利用此信息,可使暴力复杂度达到O(N2^22M2^22),代码如下:import numpy as npclass Solution: def maximalRectangle(self, matrix: List[List[str]]) -> int: if matrix == []: return 0 rows, cols = len(matrix), len(matrix[0])原创 2020-12-26 23:28:27 · 99 阅读 · 0 评论 -
leetcode 1438 滑动窗口维护最大值最小值
解法一:两个堆这个题很容易让人联想到上次的两个堆维护中位数的问题。相似的,这个题也可以用两个堆加上延迟删除分别维持最大值和最小值,复杂度为O(NlogN)。还有一个数据结构能达到和两个堆相似的效果,即平衡二叉树。from heapq import *from collections import defaultdictclass Solution: def longestSubarray(self, nums: List[int], limit: int) -> int:原创 2021-02-21 18:13:35 · 235 阅读 · 0 评论 -
leetcode 232 用栈实现队列
这个题是很有趣也很强的一道题。首先栈是不可能完美实现队列的,每次peek或者pop都会导致一次接近O(N)的操作,把左边数组移到右边。然后就不用管了。如果右边有数就都是O(1)的操作。class MyQueue: def __init__(self): """ Initialize your data structure here. """ self.s1 = [] self.s2 = [] self原创 2021-03-05 13:33:32 · 57 阅读 · 0 评论 -
leetcode 503 循环数组 单调栈
本题的循环数组,之前没听过,这次学到了。就是首尾相接的数组,并不是数组内部循环。而这个题实现方法为单调栈,若前面N个都是递减的,那他们的最大数只有一个,没有必要O(N方)。循环数组只要遍历两次即可。class Solution: def nextGreaterElements(self, nums: List[int]) -> List[int]: ret = [-1 for _ in nums] ct, i = 0, 0 stack = [原创 2021-03-06 12:19:10 · 235 阅读 · 0 评论 -
剑指offer 06 倒叙输出链表 先进后出
解法一:双端队列由于插入是O(1)操作,所以插入后转换成list即可。解法二:栈题目要求先进后出,这就是个栈,这样实现会更为简洁。因为栈比较简单,这两个的复杂度应该是相同的。在实际操作中,由于不需要打印,我么把列表反转下即可。...原创 2021-03-09 11:00:41 · 63 阅读 · 0 评论 -
leetcode 224 括号匹配
此题准确的说是一个括号匹配问题,我们可以从里到外拆解问题。每遇到一个后括号,就把前面的提出来解决,这样就没有内层了,可以用栈实现,代码如下:class Solution: def calculate(self, s: str) -> int: if len(s) == 0: return 0 stack = [] def process(): l = [] last, tmp, pos = 's原创 2021-03-10 11:52:42 · 51 阅读 · 0 评论 -
剑指offer 09 队列和栈相互转换
用两个栈实现队列,摊还复杂度是O(1)。由于是老元素先出,咱们用另一个栈存老元素就行。用两个队列实现栈,我的解法是push时是O(N)的。由于栈是新元素先出,你不可能把所有新元素预存,所以你可以在push时把新元素放入底部,把另一堆排列好的老元素加进来。这样每次只用一个队列即可。from collections import dequeclass MyStack: def __init__(self): """ Initialize your data str原创 2021-03-12 15:23:38 · 116 阅读 · 0 评论 -
leetcode 331 前序遍历 单调栈 出度入度
本题要验证前序遍历是否合理,由于是个递归的题目,很容易想到用栈处理,不断处理最内层再规约就好,代码也很简单。但这并不是最优答案,同样的解法咱们可以直接用从后向前的方法,不需要栈,直接合并。最后是两个#号,直接按照老方法合并即可,这样可以实现O(1)的空间复杂度。class Solution: def isValidSerialization(self, preorder: str) -> bool: stack = [] s = preorder.split原创 2021-03-12 21:38:11 · 209 阅读 · 0 评论 -
leetcode 84 柱状图最大矩形问题 单调栈
此题一个比较好的思路是中心扩散法,即对每个柱子,找到以他为最小值的区间。这个状态比较难用dp优化,因为不确定区间中到底包含几个最小值。另一个很好的O(N)思路就是单调栈,保持栈是一个递增序列,这样这个序列是共享同一个最小值的。当新的最小值出现,这个序列可以把之前比他大的元素排掉(此元素两端最长扩散长度已经出现)并记录他们的结果,留下序列长度让新的最小值用。如此往复即可完成操作。直接存其实是很难做的,因为要记录已经排出的柱子。最好的办法是把索引存进去,可以通过索引比较距离。...原创 2021-03-12 21:56:11 · 84 阅读 · 0 评论 -
ZJ14 最大子区间 单调栈问题
此题其实和leetcode 84题解法是相同的。找到最小值,中心扩散求最大边界,取最大值。单调栈可以很方便的找到他的边界。此题的一点变化是我们需要构建一个前缀和数组。N = int(input())nums = [0] + list(map(int, input().split(' '))) + [0]pre = [0 for _ in nums]# 构建前缀和数组sum0 = 0for i, num in enumerate(nums): sum0 += num pre[i]原创 2021-03-13 16:26:05 · 153 阅读 · 0 评论 -
leetcode 42 接雨水 单调栈+双指针
初始思路:单调栈这是个不太寻常的单调栈,但也是可以做的。思路是,如果一直递减,就留着。如果递增,看看左边有没有护着的,有就计数,没有就继续往左走。这样能循环的不断加较低的水坑,挺难想的其实。class Solution: def trap(self, height: List[int]) -> int: if not height: return 0 stack = [] ret = 0 for i, h i原创 2021-03-17 13:53:57 · 95 阅读 · 0 评论 -
leetcode 5704 包含特定元素 单调栈
此题还是熟悉的找最小值最大区间问题。不同的是加了一个k,要求必须包含索引k的元素。这个要想明白左边界和右边界,左边界很好说,就是左边的元素+1,右边界始终是i-1.因为递增的存入了栈,那些大的始终都在区间内。class Solution {public: int maximumScore(vector<int>& nums, int k) { int ret = 0; stack<int> s; k += 1;原创 2021-03-14 15:13:19 · 60 阅读 · 0 评论