LeetCode | Stack

20. Valid Parentheses

  • 思路是左侧的符号压栈;每次遇到不是左侧的符号pop栈顶元素看一下匹不匹配(hashtable);
    • 注意几种特殊情况
    1. [: stack最后还有残余;
    2. ]:起始元素是右侧元素;
    3. {(}):乱搭;
class Solution:
    def isValid(self, s: str) :
        dic = {'(':')', '{':'}', '[':']'}

        stack = []
        for char in s:
            if char in dic:
                stack.append(char)
            else:
                if stack:
                    tmp = stack.pop()
                    if dic[tmp] != char:
                        return False  # 3.
                else:
                    return False      # 2.
        return not stack              # 1.

155. Min Stack

  • 一个栈stack正常,一个栈helper维护一个最小栈orz,在insert和pop时候需要对helper动态修改;
  • 时空复杂度蛮高…
class MinStack:
    def __init__(self):
        self.stack = []
        self.helper = []

    def push(self, val: int):
        self.stack.append(val)
        
        # 动态修改helper
        if self.helper and self.helper[-1] < val:
            for index in range(len(self.helper)):
                if self.helper[index] < val:
                    self.helper.insert(index, val)
                    break
        else:
            self.helper.append(val)

    def pop(self):
        tmp = self.stack.pop()
        
        # 动态修改helper
        for index in range(len(self.helper)):
            if self.helper[index] == tmp:
                del self.helper[index]
                break
    def top(self):
        return self.stack[-1]

    def getMin(self):
        return self.helper[-1]

150. Evaluate Reverse Polish Notation

  • 很显然的一个stack的应用
    1. 不是op的压栈;
    2. 遇到op的pop出两个元素,op之后压栈;
    3. 输出;
class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        stack = []
        op = ['+', '-', '*', '/']
        tmp = 0

        for token in tokens:
            if token not in op:
                stack.append(token)
            else:
                right = int(stack.pop())
                left = int(stack.pop())
                if token == '+':
                    tmp = left + right
                if token == '-':
                    tmp = left - right
                if token == '*':
                    tmp = left * right
                if token == '/':
                    tmp = left / right
                stack.append(tmp)
        return int(stack[-1])

22. Generate Parentheses

739. Daily Temperatures

  • 维护一个单调栈,栈内存放的元素从底部是降序的【ps:存的Index,后面要用计算距离】
    • 若新的元素<栈顶元素:压栈;
    • 若新的元素>栈顶元素:pop栈顶元素[while直到到第一种情况]
    • 所以while的条件就综合成为while stack and t[stack[-1]] < t[index];
class Solution:
    def dailyTemperatures(self, t):
        stack = []
        res = [0] * len(t)

        for index in range(len(t)):
            while stack and t[stack[-1]] < t[index]:
                index2 = stack.pop()
                res[index2] = index - index2
            stack.append(index)
        return res

853. Car Fleet

在这里插入图片描述
在这里插入图片描述

  • 哈哈哈哈每次做不出来看到nc的图解都要大呼精彩!
    • 每辆车如果可以在目的地前(包括目的地)追上,由于是单行道,集体降速哈哈哈哈;
    • nc的思路是转化成到达target的时间t,维护一个stack存放按position大小降序排列的🚗到达target的时间;
      • 对每个t压栈,都和压栈前的栈顶t做比较,如果当前压栈的t更小,那么说明是一个车队了,我们选择保留原车头就可以了,所以把当前压栈的 t pop掉;

嘶就是按position降序后,每辆车计算一下到target的时间t,[t1,t2,…,tn];问题转化成739的问题,比739还简单一点,只需要维护一个单调栈,栈顶元素为当前最大值(递增的栈);
好吧 批了皮(sorted+计算t)我就不认得它了…
nc的原版是ver1,但是我不喜欢先压栈2333,ver2比较对我的习惯2333

class Solution:
    def carFleet(self, target, position, speed):
        pair = [[p, s] for p, s in zip(position, speed)]
        stack = []

        for p, s in sorted(pair)[::-1]:
            stack.append((target - p) / s)
            if len(stack) >= 2 and stack[-1] <= stack[-2]:
                stack.pop()
        return len(stack)
        
    def carFleet2(self, target, position, speed):
        pair = sorted([[p, s] for p, s in zip(position, speed)])[::-1]
        stack = [(target - pair[0][0]) / pair[0][1]]

        for p, s in pair[1:]:
            cur = (target - p) / s
            if cur > stack[-1]:
                stack.append(cur)
        return len(stack)

84. Largest Rectangle in Histogram

nc yyds!!!
问题拆解!问题拆解!!问题拆解!!!

  • 思路:维护一个单调栈;
  • 从图1开始:三个特殊情况;当前长后短时,长的无法extend,以它为height的高度的只有他自己[形象点就是拿一把刀切从它height切过去,只有它自己会受伤嗯],所以它既然不能extend伤害别人,就把他pop出来【好家伙,寻思着是一个恶人栈吗】;当前短后长时或者前后等长时,我们就把他们留在栈内,他们这个height切过去很有杀伤力哈哈哈哈;

在这里插入图片描述

  • 这里会有一个trick:
    • stack里存的是pair:index, height,不是会出现前长后短然后把这个长的pop掉,那么我们的问题是,要append的这个短的Index应该是什么呢?
    • !是的!我们要注意到!我们pop掉的都是比现在我们要Insert的height都要大的!最后一个pop掉的index是我们可以向前extend当前height的最大长度[为后面计算留在单调栈里的Area做铺垫啦]![因为我们前面维护的就是一个单调非降栈哈哈,所以你停下来的时候,你当前的栈顶元素已经比你小了,所以你没法继续向前extend啦]!

谁人不说一句妙呢???我菜我先说了哈哈哈哈!
在这里插入图片描述

  • 总的来说是求最大的矩形面积nc的想法是分成两步来完成:
    1. 构造单调栈:当前压栈为栈内的最大height;顺便计算被pop出来的元素的最大矩形面积;压栈记得index的trick;
    2. 单调栈内height的最大矩形面积更新maxArea;
class Solution:
    def largestRectangleArea(self, heights):
        stack = []
        maxArea = 0
        
        for index, height in enumerate(heights):
            start = index
            while stack and height < stack[-1][1]:
                index2, height2 = stack.pop()
                maxArea = max(maxArea, height2 * (index - index2))
                start = index2
            stack.append([start, height])
        
        for index, height in stack:
            maxArea = max(maxArea, height * (len(heights) - index))
        
        return maxArea

I am glad I finally did. 泪目了啊!向blog主学习!
的确发现nc的花费的额外的空间开销更容易理解一些2333,是我愚钝了!

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值