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
相关推荐
天天扭码21 分钟前
一分钟吃透一道面试算法题——字母异位词分组(最优解)
前端·javascript·算法
网络安全研发随想22 分钟前
C语言核心结构+难点精讲+工程技巧
c语言·开发语言·算法
李煜鑫1 小时前
关于视频的一些算法内容,不包含代码等
算法·音视频·语音识别
get lend gua1 小时前
游戏数据分析,力扣(游戏玩法分析 I~V)mysql+pandas
python·mysql·leetcode·游戏·数据分析
我爱工作&工作love我1 小时前
【深基18.例3】查找文献-图的储存与遍历
算法·深度优先·图论
心软且酷丶1 小时前
leetcode:2899. 上一个遍历的整数(python3解法)
python·算法·leetcode
啾啾Fun1 小时前
数据结构与算法学习导航
学习·算法
AI技术控2 小时前
计算机视觉算法实战——基于YOLOv8的农田智能虫情测报灯害虫种类识别系统开发指南
人工智能·深度学习·算法·yolo·计算机视觉
PHASELESS4112 小时前
Java排序算法百科全书:原理、实现与实战指南
java·数据结构·算法·排序算法
末央&2 小时前
【C++】特化妙技与分文件编写 “雷区”
开发语言·c++·算法