LeetCode刷题---栈及单调栈相关题目I

本文介绍了如何使用栈解决LeetCode中的几种数据结构问题,包括最小栈、有效括号验证、单调栈的应用,如每日温度、下一个最大元素和链表中的下一个更大节点。通过实例详细解析了单调栈的解题思路,帮助读者加深对栈和单调栈的理解。
摘要由CSDN通过智能技术生成


前言

  本博客总结了一些与栈相关的leetcode题目,记录一下,时常复习。

一、栈是什么?

  栈遵循:先进后出原则。
栈的图解

二、Leetcode题目

1.Leetcode155-最小栈

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

  • push(x) – 将元素 x 推入栈中。
  • pop() – 删除栈顶的元素。
  • top() – 获取栈顶元素。
  • getMin() – 检索栈中的最小元素
class MinStack(object):

    def __init__(self):
        self.stack = []  # 存放所有元素
        self.minStack = []  # 存放每一次压入数据时,栈中的最小值
    def push(self, x):
        self.stack.append(x)
        if not self.minStack or self.minStack[-1] >= x:
            self.minStack.append(x)
    def pop(self):  # 移除栈顶元素时,判断是否移除栈中最小值
        if self.minStack[-1] == self.stack[-1]:
            del self.minStack[-1]
        self.stack.pop()
    def top(self):
        return self.stack[-1]
    def getMin(self):
        return self.minStack[-1]

2.Leetcode20-有效的括号

题目:
  给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。
class Solution:
    def isValid(self, s):
        mapping = {")": "(", "]": "[", "}": "{"}
        stack = []
        for i, char in enumerate(s):
            if char not in mapping:  # left
                stack.append(char)
            else:
                if not stack or stack[-1] != mapping[char]:
                    return False
                stack.pop()
        return len(stack) == 0

三、单调栈Leetcode相关题目

  单调栈即栈内的数据严格单调递增或者严格单调递减。

3.1 Leetcode739-每日温度

题目:
  根据每日气温列表,请重新生成一个列表,对应位置的输入是你需要再等待多久温度才会升高的天数。如果之后都不会升高,请输入0来代替。

  • 例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73]
  • 你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
class Solution(object):
    def dailyTemperatures(self, T):
        ans = [0] * len(T)
        stack = []
        for i, t in enumerate(T):
            while stack and T[stack[-1]] < t:
                prev_idx = stack.pop()
                ans[prev_idx] = i - prev_idx
            stack.append(i)
        return ans

3.2 Leetcode496-下一个最大元素I

题目:
  给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出-1。

# 暴力查找 
class Solution(object):
    def nextGreaterElement(self, nums1, nums2):
        if not nums1 or not nums2:
            return []
        ans = []
        for item in nums1:
            index = nums2.index(item)
            for i in range(index, len(nums2)):
                if nums2[i] > item:
                    ans.append(nums2[i])
                    break
            if i + 1 == len(nums2) and nums2[-1] <= item:
                ans.append(-1)
        return ans
# 用栈
class Solution(object):
    def nextGreaterElement(self, nums1, nums2):
        mapping = dict()
        stack = []
        # 遍历nums2中的所有元素,找到比下个元素大的数存入mapping中,采用哈希表的思想
        for num in nums2:
            while stack and stack[-1] < num:
                top = stack.pop()
                mapping[top] = num
            stack.append(num)
        # 遍历nums1中的元素,看看是否在mapping中出现,若有输出,否则输出-1
        ans = []
        for num in nums1:
            if num in mapping:
                ans.append(mapping[num])
            else:
                ans.append(-1)
        return ans

3.3 Leetcode503-下一个最大元素II

题目:
   给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。
数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,
这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。
-----------------------------------------------------------------------------------
示例:
输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

class Solution:
    def nextGreaterElements(self, nums):
        length = len(nums)
        ans = [-1 for i in range(length)]
        stack = []
        # 列表的拼接构成循环队列
        double = nums + nums
        for idx, num in enumerate(double):
            while stack and nums[stack[-1]] < num:
                ans[stack[-1]] = num
                stack.pop()
            if idx < length:
                stack.append(idx)
        return ans

3.4 Leetcode1019-链表中的下一个更大节点

题目:
   给出一个以头节点 head 作为第一个节点的链表。链表中的节点分别编号为:node_1, node_2, node_3, …
每个节点都可能有下一个更大值(next larger value):
对于 node_i,如果其 next_larger(node_i) 是 node_j.val,那么就有 j > i 且 node_j.val> node_i.val
而 j 是可能的选项中最小的那个。如果不存在这样的 j ,那么下一个更大值为 0 。
返回整数答案数组 answer,其中 answer[i] = next_larger(node_{i+1}) 。
-----------------------------------------------------------------------------------------------
示例1:
输入:[2,1,5]
输出:[5,5,0]
示例2:
输入:[2,7,4,3,5]
输出:[7,0,5,5,0]

class Solution(object):
    def nextLargerNodes(self, head):
        """
        :type head: ListNode
        :rtype: List[int]
        """
        h = head
        L = list()
        #把链表转数组
        while(h): 
            L.append(h.val)
            h = h.next
        stack = list()
        ans = [0 for i in range(len(L))]
        cnt = 0
        while(cnt < (len(L))):
            if not stack or L[stack[-1]] >= L[cnt]:
                stack.append(cnt)
            else:
                while(stack and L[stack[-1]] < L[cnt]): 
                    ans[stack[-1]] = L[cnt]                    
                    stack.pop()
                stack.append(cnt)
                
            cnt += 1
        return ans

总结

  对单调栈的解题思路有了充分的理解,加油,刷题崽!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

「已注销」

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值