leetcode刷题-单调栈

代码随想录单调栈|739. 每日温度、496.下一个更大元素 I、503.下一个更大元素II、42. 接雨水、84.柱状图中最大的矩形

739. 每日温度

leetcode题目链接
代码随想录文档讲解

思路

找到这个元素后面 第一个比这个元素大的元素,算它们的距离(下标之差)

暴力解法:时间复杂度n2

单调栈:时间复杂度n2

单调栈适合:求当前元素左边(右边)比当前元素大(小)的元素

单调栈中存放的是下标,存放的元素是递增(从栈顶到栈底)还是递减呢?递增(第一个比它大的元素),递减(第一个比它小的元素)

单调栈的作用: 记录遍历过的元素!!

python代码

python 复制代码
class Solution:
    def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
        answer = [0]*len(temperatures)
        stack = [0] # 存放下标
        for i in range(1, len(temperatures)):
            if temperatures[i] <= temperatures[stack[-1]]:
                stack.append(i)
            else:
                while len(stack) != 0 and temperatures[i] > temperatures[stack[-1]]:
                    answer[stack[-1]] = i - stack[-1]
                    stack.pop()
                stack.append(i)
        return answer

496.下一个更大元素 I

leetcode题目链接
代码随想录文档讲解

思路

本题本质还是对nums2采用单调栈的算法计算下一个最大元素,但是返回的result需要和nums1大小一致,顺序一致,因此对nums2中的元素计算完后需要映射回nums1,除此之外,本题的result数组应该初始化为-1

两个没有重复元素 的数组 nums1 和 nums2,采用map进行映射,使用哈希表数据结构,但是对于python实现,可以使用index函数

python代码

python index函数

nums1 = [1, 3, 5, 7]

nums1.index(5) 输出: 2

python 复制代码
class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        result = [-1]*len(nums1)
        stack = [0]
        for i in range(1, len(nums2)):
            if nums2[i] <= nums2[stack[-1]]:
                stack.append(i)
            else:
                while len(stack)!= 0 and nums2[i] > nums2[stack[-1]]:
                    if nums2[stack[-1]] in nums1: # 这里注意不要写反了,nums2[stack[-1]]和nums2[i]
                        index = nums1.index(nums2[stack[-1]])
                        result[index] = nums2[i]
                    stack.pop()
                stack.append(i)
        return result

503.下一个更大元素II

leetcode题目链接
代码随想录文档讲解

思路

本题相比前面两题,变为循环数组了(数组可以首尾相连了)

思路1: 扩容,两个数组拼在一起,然后单调栈

例如:nums = [1,2,1],扩容后:nums = [1,2,1,1,2,1]

result = [2,-1,2,2,-1,_] 取前3个即:[2,-1,2]

思路2: 用取模的方式模拟转圈的过程 (设计成环都可以这么操作)

for i in range(len(nums)*2):

i = i%len(nums)

遍历时对数组长度×2,然后实际再进行取模,所以在超出数组长度的时候,i又回来了

python代码

n = [1, 2, 3]

n*2 输出:[1, 2, 3, 1, 2, 3]

n+n 输出:[1, 2, 3, 1, 2, 3]

python 复制代码
# 思路1
class Solution:
    def nextGreaterElements(self, nums: List[int]) -> List[int]:
        n = len(nums)
        nums = nums*2
        result = [-1]*len(nums)
        stack = [0]
        for i in range(1, len(nums)):
            if nums[i] <= nums[stack[-1]]:
                stack.append(i)
            else:
                while len(stack) != 0 and nums[i] > nums[stack[-1]]:
                    result[stack[-1]] = nums[i]
                    stack.pop()
                stack.append(i)
        res = result[:n]
        return res
python 复制代码
# 思路2
class Solution:
    def nextGreaterElements(self, nums: List[int]) -> List[int]:
        result = [-1]*len(nums)
        stack = [0]
        for i in range(1, len(nums)*2):
            i = i%len(nums)
            if nums[i] <= nums[stack[-1]]:
                stack.append(i)
            else:
                while len(stack) != 0 and nums[i] > nums[stack[-1]]:
                    result[stack[-1]] = nums[i]
                    stack.pop()
                stack.append(i)
        return result

42. 接雨水 -- 面试常考题

leetcode题目链接
代码随想录文档讲解

思路

思路1: 暴力解法,复杂度n2

两层for循环,外层for循环一个遍历柱子,里层for循环 去找每个柱子右边比它高的第一个柱子高度及左边比它高的第一个柱子的高度是多少

思路2: 双指针优化,复杂度O(n)

提前预处理两个数组

思路3: 单调栈

这里可以借助单调栈的特性,栈内的元素是单调递增的,因此在获得了某一个元素的右边第一个比它大的元素,那么栈里的下一个元素就是左边第一个比它大的元素

栈中还是存放下标

python代码

python 复制代码
class Solution:
    def trap(self, height: List[int]) -> int:
        result= 0
        stack= [0]
        for i in range(1, len(height)):
            if height[i] <= height[stack[-1]]:
                stack.append(i)
            else:
                while stack and height[i] > height[stack[-1]]:
                    mid = stack.pop()
                    if stack:
                        w = i - stack[-1] - 1
                        h = min(height[i], height[stack[-1]]) - height[mid] # 第一次提交把这里重命名为height了,调试了半天。。
                        result += w*h
                stack.append(i)
        return result

84.柱状图中最大的矩形

leetcode题目链接
代码随想录文档讲解

思路

和接雨水题目遥相呼应,一个是求柱子外面的,一个是求柱子里面的

  1. 思路1: 暴力解法,复杂度n2

    两次for循环

    以某个柱子为中心,找左边比它矮的,右边比它矮的,确定高,然后根据距离确定宽

  2. 思路2: 双指针法

  3. 思路3: 单调栈

    此处的单调栈是单调递减的,因为要找左边和右边第一个比它小的,中间就是大于等于它的,高度就是当前柱子的高度,宽度为中间柱子的宽度;

    首位加0,(尾部加0)避免[2,4,6,8]这样单调递增的数组;(头部加0)对于[8,6,4,2]若满足当前元素大于栈顶元素,弹出后,栈为空,则不会进行计算面积,避免栈为空的情况

python代码

python 复制代码
class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        heights = [0] + heights + [0] # 或者 heights.insert(0, 0) heights.append(0)
        result = 0
        stack = [0]
        for i in range(1, len(heights)):
            if heights[i] >= heights[stack[-1]]:
                stack.append(i)
            else:
                while stack and heights[i] < heights[stack[-1]]:
                    mid = stack.pop()
                    if stack:
                        w = i - stack[-1] - 1
                        h = heights[mid]
                        result = max(result, w*h)
                stack.append(i) # 第一次忘记了这行代码
        return result
相关推荐
Tisfy1 小时前
LeetCode 2411.按位或最大的最小子数组长度:一次倒序遍历
数据结构·算法·leetcode·题解·位运算·遍历
2202_756749691 小时前
04 基于sklearn的机械学习-梯度下降(上)
人工智能·算法·机器学习
草莓爱芒果1 小时前
Spring Boot中使用Bouncy Castle实现SM2国密算法(与前端JS加密交互)
java·spring boot·算法
晚云与城2 小时前
【数据结构】-----排序的艺术画卷
数据结构·算法·排序算法
weixin_307779132 小时前
设计Mock CUDA库的流程与实现
c++·算法·gpu算力
j_xxx404_2 小时前
数据结构:算法复杂度与空间复杂度
c语言·数据结构·算法
dlraba8022 小时前
基于 OpenCV 与 sklearn 的数字识别:KNN 算法实践
opencv·算法·sklearn
yzzzzzzzzzzzzzzzzz3 小时前
leetcode热题——全排列
算法·回溯·全排列
王柏龙3 小时前
mongodb中的哈希索引详解
算法·mongodb·哈希算法