代码随想录训练营第60天 | 503.下一个更大元素II ● 42. 接雨水● 84.柱状图中的最大矩形

news/2025/2/21 5:38:42/

503.下一个更大元素II 

题目链接:https://leetcode.com/problems/next-greater-element-ii/

解法:

由于是循环数组,可以直接把两个数组拼接在一起,然后使用单调栈求下一个最大值。

写法上,可以巧妙一些,循环的长度为2*len(nums),通过 i%len(nums)来实现两次遍历数组。

边界条件:无

时间复杂度:O(n)

空间复杂度:O(n)

class Solution(object):def nextGreaterElements(self, nums):dp = [-1] * len(nums)stack = []for i in range(len(nums)*2):while stack and nums[i%len(nums)] > nums[stack[-1]]:dp[stack[-1]] = nums[i%len(nums)]stack.pop()stack.append(i%len(nums))return dp 

42. 接雨水

题目链接:https://leetcode.com/problems/trapping-rain-water/

解法:

按照列来计算的话,宽度一定是1了,我们再把每一列的雨水的高度求出来就可以了。

每一列雨水的高度,取决于,该列 左侧最高的柱子和右侧最高的柱子中最矮的那个柱子的高度。

使用双指针来计算。

为了得到两边的最高高度,使用了双指针来遍历,每到一个柱子都向两边遍历一遍,这其实是有重复计算的。我们把每一个位置的左边最高高度记录在一个数组上(maxLeft),右边最高高度记录在一个数组上(maxRight),这样就避免了重复计算。

单调栈的做法,代码随想录的解法写得巨复杂,直接不想看了。其实没那么复杂,但是还是很巧妙,主要出来的柱子的顺序不是从左到右的。

这个和每日温度的题目思路很像,只要找到右边第一个更大的元素,就可以把栈头pop,计算雨水面积,因为是从栈头到栈尾递增,那么左边的元素大于等于栈头,就可以储水了。

雨水高度是 min(凹槽左侧高度, 凹槽右侧高度) - 凹槽底部高度。

雨水宽度是 凹槽右侧的下标 - 凹槽左侧的下标 - 1。

题解看leetcode中文区的比较好懂:

边界条件:无

时间复杂度:O(n)

空间复杂度:O(n)

# 单调栈
class Solution(object):def trap(self, height):stack = [0]result = 0for i in range(1, len(height)):while stack and height[i] > height[stack[-1]]:idx = stack.pop()if stack:# 如果 stack[-1] 和 idx 对应的值相同,那就面试为0h = min(height[stack[-1]], height[i]) - height[idx]w = i - stack[-1] - 1result += h * wstack.append(i)return result
# 双指针
class Solution(object):def trap(self, height):max_left, max_right = [0] * len(height), [0] * len(height)max_left[0] = height[0]max_right[-1] = height[-1] # 求i左边的最大值for i in range(1, len(height)):max_left[i] = max(height[i], max_left[i-1])# 求i右边的最大值for i in range(len(height)-2, -1, -1):max_right[i] = max(height[i], max_right[i+1])result = 0for i in range(len(height)):# 取决于左遍最大值和右边最大值之间的较小值count = min(max_left[i], max_right[i]) - height[i]if count > 0:result += countreturn result

84. 柱状图中的最大矩形

题目链接:

解法:

这道题,代码随想录连怎能计算矩形的面积都没写,就直接给了代码,默认大家懂了... 

这题看leetcode的中文区解法比较好。

计算矩形的最大面积,可以枚举以每个柱形为高度的最大矩形的面积。

为此,我们需要:

左边看一下,看最多能向左延伸多长,找到大于等于当前柱形高度的最左边元素的下标;
右边看一下,看最多能向右延伸多长;找到大于等于当前柱形高度的最右边元素的下标。
对于每一个位置,我们都这样操作,得到一个矩形面积,求出它们的最大值。

所以,双指针的写法,可以记录每个元素的左边第一个更小元素的下标和右边第一个更小元素的下标,那么面积等于 (right_min - left_min - 1) * height[i].

相比之下,单调栈的写法简洁多了。这里用的单调减栈,也就是栈头到栈尾是递减的(列表表现为从左到右递增)。

42. 接雨水 (opens new window)是找每个柱子左右两边第一个大于该柱子高度的柱子,而本题是找每个柱子左右两边第一个小于该柱子的柱子。不同的是,接雨水第一个柱子和最后一个柱子没法储水,但这里第一个柱子和最后一个都要计算以他们为高度的面积,所以heights的前后要插入0。

边界条件:无

时间复杂度:双指针O(n)

空间复杂度:双指针O(n)

# 双指针 
class Solution:def largestRectangleArea(self, heights: List[int]) -> int:size = len(heights)# 两个DP数列储存的均是下标indexmin_left_index = [0] * sizemin_right_index = [0] * sizeresult = 0# 记录每个柱子的左侧第一个矮一级的柱子的下标min_left_index[0] = -1  # 初始化防止while死循环for i in range(1, size):# 以当前柱子为主心骨,向左迭代寻找次级柱子temp = i - 1while temp >= 0 and heights[temp] >= heights[i]:# 当左侧的柱子持续较高时,尝试这个高柱子自己的次级柱子(DPtemp = min_left_index[temp]# 当找到左侧矮一级的目标柱子时min_left_index[i] = temp# 记录每个柱子的右侧第一个矮一级的柱子的下标min_right_index[size-1] = size  # 初始化防止while死循环for i in range(size-2, -1, -1):# 以当前柱子为主心骨,向右迭代寻找次级柱子temp = i + 1while temp < size and heights[temp] >= heights[i]:# 当右侧的柱子持续较高时,尝试这个高柱子自己的次级柱子(DPtemp = min_right_index[temp]# 当找到右侧矮一级的目标柱子时min_right_index[i] = tempfor i in range(size):area = heights[i] * (min_right_index[i] - min_left_index[i] - 1)result = max(area, result)return result

class Solution(object):def largestRectangleArea(self, heights):heights.insert(0, 0)heights.append(0)stack = [0]result = 0for i in range(1, len(heights)):# 维持的单调减栈,左边元素肯定更小,右边遇到更小的就计算面积while stack and heights[i] < heights[stack[-1]]:mid_idx = stack.pop()if stack:h = heights[mid_idx]w = i - stack[-1] - 1result = max(result, h * w)stack.append(i)return result


http://www.ppmy.cn/news/1197310.html

相关文章

Docker 安装ELK7.7.1

(注&#xff1a;在安装之前&#xff0c;本方法必须安装jdk1.8以上版本) (注&#xff1a;如果在虚拟机下用可以直接按方法走即可&#xff0c;如果是想进行备份后在别的机器上进行相关操作&#xff0c;必须把所有带有172.17.0.6、192.168.8.166:9200和端口号都改成你自己的方可使…

【Java-框架-Mybatis】(01) 使用Mybatis框架操作MySQL数据库,快速上手

前言 使用"Mybatis"框架操作"MySQL"数据库&#xff0c;快速上手&#xff1b; 实操一 【说明】 通过"IntelliJ IDEA"软件来创建"Maven"项目&#xff1b;通过"Mybatis"框架完成"MySQL"数据库操作&#xff1b; 【环…

Java面试题-Redis-第三天(缓存更新策略-由旁路缓存策略衍生出的一系列问题)

1. 问&#xff1a;了解缓存更新策略吗&#xff1f; 了解 先说旁路缓存策略 说了那个写策略 2. 问&#xff1a;然后问为什么要用那种&#xff1a; 答&#xff1a;降低不一致情况出现 3. 问&#xff1a;为什么会不一致&#xff1f; 答&#xff1a;请求1先将缓存删了&#xff0c;…

UML 2.0包括14种图

UML 2.0包括14种图&#xff0c;分别如下&#xff1a; &#xff08;1&#xff09;类图&#xff08;class diagram&#xff09;。类图描述一组类、接口、协作和它们之间的关系。类图给出了系统的静态设计视图&#xff0c;活动类的类图给出了系统的静态进程视图。 &#xff08;2…

[极客大挑战 2019]LoveSQL 1

题目环境&#xff1a;判断注入类型是否为数字型注入 admin 1 回显结果 否 是否为字符型注入 admin 1 回显结果 是 判断注入手法类型 使用堆叠注入 采用密码参数进行注入 爆数据库1; show database();#回显结果 这里猜测注入语句某字段被过滤&#xff0c;或者是’;被过滤导致不能…

虚拟dom及diff算法之 —— snabbdom

源码&#xff1a;https://github.com/snabbdom/snabbdom 测试环境搭建 npm i -S snabbdom 安装好的node_modules提供了js和ts的代码&#xff1a;build&#xff1a;js代码&#xff0c;src&#xff1a;ts代码 npm i -D webpack5 webpack-cli3 webpack-dev-server3 webpack&#x…

苹果cms论坛多播放源自动采集在线影视网站

苹果 cms 论坛一个基于 vue 和 gin 实现的在线观影网站 项目采用 vite vue 作为前端技术栈, 使用 ElementPlus 作为 UI 框架进行开发 后端程序使用 Gin gorm go-redis 等相关框架提供接口服务, 使用 gocolly 和 robfig/cron 进行公共影视资源采集和定时更新功能 目前用户…

Visual Studio Code 快 捷 键

个人总结 Visual Studio Code 快 捷 键&#xff01;满足日常使用&#xff0c;提高工作效率&#xff01;&#xff01; 1、搜索文件&#xff1a; Ctrl p 2、移到某一行&#xff1a; Ctrl g 一、切 换 行 注 释、切 换 块 注 释 1、行注释"//"快捷键&#xf…