【Leetcode】top 100 栈

基础知识补充

1.栈是一种运算受限的线性表,仅允许在一端进行插入和删除操作;

2.可用列表实现,list.append(val) // list.pop()

题目
20 有效的括号

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。
class Solution(object):
    def isValid(self, s):
        """
        :type s: str
        :rtype: bool
        """
        stack = []
        for strr in s:
            if strr=='(' or strr=='[' or strr=='{':    #左括号,入栈
                stack.append(strr)
            else:                                      #右括号,判断是否匹配
                if not stack: return False
                else:
                    pre = stack.pop()
                    if strr == ')' and pre != '(': return False
                    elif strr == ']' and pre != '[': return False
                    elif strr == '}' and pre != '{': return False    

        return stack==[] 

写完初步代码发现实际上需要找的是右括号,然后判断右括号是否与对应左括号匹配,可以用 dict 构造成对关系

class Solution(object):
    def isValid(self, s):
        """
        :type s: str
        :rtype: bool
        """
        stack = []
        dict = {')':'(', ']':'[', '}':'{'}

        for strr in s:
            if not stack: stack.append(strr)
            else:                                     
                if strr in dict:     # 右括号,判断是否匹配
                    if stack[-1]==dict[strr]: stack.pop()
                    else: return False
                else:                # 左括号,入栈
                    stack.append(strr)

        return not stack 
 155 最小栈

 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

  • MinStack() 初始化堆栈对象。
  • void push(int val) 将元素val推入堆栈。
  • void pop() 删除堆栈顶部的元素。
  • int top() 获取堆栈顶部的元素。
  • int getMin() 获取堆栈中的最小元素。

正常维护一个栈完成入栈、出栈、取栈顶元素操作;

要求在常数时间内检索到最小元素,即用变量记录当前栈的最小值,与正常栈一起维护;

class MinStack(object):

    def __init__(self):
        self.stack = []
        self.min = 2**31

    def push(self, val):
        """
        :type val: int
        :rtype: None
        """
        if not self.stack: self.stack.append([val, val])
        else:
            self.stack.append([val, min(val, self.stack[-1][1])])
            

    def pop(self):
        """
        :rtype: None
        """
        if self.stack: self.stack.pop()

    def top(self):
        """
        :rtype: int
        """
        if self.stack: 
            nums = self.stack.pop()
            self.stack.append(nums)
            return nums[0]
        
    def getMin(self):
        """
        :rtype: int
        """
        if self.stack: 
            nums = self.stack.pop()
            self.stack.append(nums)
            return nums[1]
 394 字符串解码

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

class Solution(object):
    def decodeString(self, s):
        """
        :type s: str
        :rtype: str
        """
        stack = []
        for strr in s:
            if strr != ']': stack.append(strr)
            else:
                res, num, bit = [], 0, 1
                while stack:
                    if stack[-1]=='[': break
                    val = stack.pop()
                    res = list(val) + res    # 注意先后顺序
                stack.pop()
                while stack:
                    val = stack.pop()
                    if val>='0' and val<='9':
                        # num = val + num       也可以用字符串
                        num = num+int(val)*bit      
                        bit = bit*10
                    else: 
                        stack.append(val)
                        break
                stack.append(''.join(res*num))
        return ''.join(stack)
739 每日温度

给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。

 维护一个递减的单调栈,初始化间隔变量interval,若入栈元素大于栈顶元素,弹出栈顶元素并将其对应的输出坐标置为interval,然后 interval+1,继续循环至前一个大于等于当前元素的值;

问题出在怎么通过弹出的元素定位到其输出坐标?  坐标表示,即栈内维护的是温度对应的下标,间隔 interval 就自然转化为入栈元素下标和出栈元素下标的差值;

class Solution(object):
    def dailyTemperatures(self, temperatures):
        """
        :type temperatures: List[int]
        :rtype: List[int]
        """
        stack = []
        out = [0] * len(temperatures)
        # for i, tmp in enumerate(temperatures):
        #     if not stack or temperatures[stack[-1]] >= tmp:   # 栈空/前一温度大于等于当前温度
        #         stack.append(i)
        #     else:                                             # 前一温度小于当前温度
        #         while stack:
        #             if temperatures[stack[-1]] >= tmp:break   # 直至遇到前一温度大于等于当前温度
        #             else:
        #                 idx = stack.pop()
        #                 out[idx] = i-idx
        #         stack.append(i)
        
        # if/else 都要 append 简化一下:
        for i, tmp in enumerate(temperatures):
            while stack and temperatures[stack[-1]] < tmp:
                idx = stack.pop()
                out[idx] = i-idx
            stack.append(i)
                        
        return out
 84 柱状图中的最大矩形

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

对于高度为 height[i] 的矩形,最大面积的宽为其左右第一个小于该高度的元素下标差-1,故将问题转换为给定高度为 height[i],求其左右第一个小于该高度的元素下标差;

left[i] 为 height[i] 的左界下标,right[i] 为 height[i] 的右界下标;单调栈问题

class Solution(object):
    def largestRectangleArea(self, heights):
        """
        :type heights: List[int]
        :rtype: int
        """
        n = len(heights)
        left, right = [-1]*n, [n]*n
        stack = []
        for i in range(n):
            while stack and heights[stack[-1]] >= heights[i]: # 找到val的左界
                stack.pop()
            if stack: left[i] = stack[-1]
            stack.append(i)
        print(left)

        stack = []
        for i in range(n-1, -1, -1):         
            while stack and heights[stack[-1]] >= heights[i]: # 找到val的右界
                stack.pop()
            if stack: right[i] = stack[-1]
            stack.append(i)
        print(right)
        
        out = 0
        for i in range(n):
            ans = heights[i]*(right[i]-left[i]-1)
            out = max(ans, out)
        return out

42接雨水 类似,待后续一起总结

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值