当前位置: 首页 > news >正文

单调栈(打卡)

本篇基于b站灵茶山艾府。

下面是灵神上课讲解的题目与课后作业,课后作业还有三道实在写不下去了,下次再写。

739. 每日温度

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

示例 1:

输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]

示例 2:

输入: temperatures = [30,40,50,60]
输出: [1,1,1,0]

示例 3:

输入: temperatures = [30,60,90]
输出: [1,1,0]

class Solution:def dailyTemperatures(self, temperatures: List[int]) -> List[int]:# 1.从右到左# st = []  # 存储的是下标# ans = [0] * len(temperatures)# for i in range(len(temperatures) - 1, -1, -1):#     t = temperatures[i]#     while st and temperatures[st[-1]] <= t:#         # 如果栈中有元素且栈口温度小于等于当前温度,则栈口的温度不可能是前面温度的答案,弹出#         st.pop()#     # 如果栈不为空,说明后面存在比当前温度高的温度,记录答案#     if st:#         ans[i] = st[-1] - i#     # 当前温度进栈#     st.append(i)# return ans# 2.从左到右st = []     # 栈内存储的是还没记录答案的每日温度ans = [0] * len(temperatures)for i, t in enumerate(temperatures):# 如果栈不为空且当前温度大于栈口元素,说明当前温度是栈口温度的答案while st and t > temperatures[st[-1]]:ans[st[-1]] = i - st[-1]st.pop()# 进栈st.append(i)return ans# 第一种做法相当于每轮循环都会记录当天的答案# 第二种做法相当于只有在弹出栈时才记录答案


42. 接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 1:

img

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 

示例 2:

输入:height = [4,2,0,3,2,5]
输出:9

class Solution:def trap(self, height: List[int]) -> int:# 横着看,当前柱子什么时候能接水?# 当后面柱子的高度超过当前柱子的高度时,就能接水了st = []  # 栈内元素单调递增s = 0for i, right_h in enumerate(height):while st and height[st[-1]] < right_h:# 如果当前柱子高度大于栈口元素高度,说明栈口元素的柱子是能接水的mid_h = height[st.pop()]  # 栈口元素高度# 如果栈中没有柱子了,那水会从左边流出去,退出if not st:breakleft_h = height[st[-1]]  # 左边数字的高度w = i - st[-1] - 1  # 宽度h = min(left_h, right_h) - mid_h  # 高度s += w * h  # 面积st.append(i)return s


496. 下一个更大元素 I

nums1 中数字 x下一个更大元素 是指 xnums2 中对应位置 右侧第一个x 大的元素。

给你两个 没有重复元素 的数组 nums1nums2 ,下标从 0 开始计数,其中nums1nums2 的子集。

对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j]下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1

返回一个长度为 nums1.length 的数组 ans 作为答案,满足 ans[i] 是如上所述的 下一个更大元素

示例 1:

输入:nums1 = [4,1,2], nums2 = [1,3,4,2].
输出:[-1,3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 4 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
- 1 ,用加粗斜体标识,nums2 = [1,3,4,2]。下一个更大元素是 3 。
- 2 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。

示例 2:

输入:nums1 = [2,4], nums2 = [1,2,3,4].
输出:[3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 2 ,用加粗斜体标识,nums2 = [1,2,3,4]。下一个更大元素是 3 。
- 4 ,用加粗斜体标识,nums2 = [1,2,3,4]。不存在下一个更大元素,所以答案是 -1 。

class Solution:def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:idx = {x: i for i, x in enumerate(nums1)}st = []ans = [-1] * len(nums1)# 1.从左向右# for i, x in enumerate(nums2):#     # 如果当前元素大于栈口元素,说明可以记录在栈口的答案了#     while st and x > nums2[st[-1]]:#         j = st.pop()#         if nums2[j] in idx:     # 如果栈口元素在nums1中#             ans[idx[nums2[j]]] = x  # 记录答案#     st.append(i)    # 元素进栈# return ans# 2.从右到左for i in range(len(nums2) - 1, -1, -1):num = nums2[i]# 如果当前元素大于等于栈口元素,说明栈口的元素永远不可能是前面元素的答案,出栈while st and num >= nums2[st[-1]]:st.pop()# 如果栈不为空,此时栈口元素大于当前元素,说明可以记录当前元素的答案了if st and num in idx:ans[idx[num]] = nums2[st[-1]]st.append(i)    # 元素进栈return ans


503. 下一个更大元素 II

给定一个循环数组 numsnums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素

数字 x下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1

示例 1:

输入: nums = [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数; 
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

示例 2:

输入: nums = [1,2,3,4,3]
输出: [2,3,4,-1,4]

class Solution:def nextGreaterElements(self, nums: List[int]) -> List[int]:# 循环两遍元素,确保下一个更大元素在循环搜索中发现st = []ans = [-1] * len(nums)n = len(nums)# 1. 从左向右# for i in range(n * 2):#     num = nums[i % n]#     while st and num > nums[st[-1]]:#         j = st.pop()#         ans[j] = num#     st.append(i % n)# return ans# 2.从右向左for i in range(n * 2 - 1, -1, -1):num = nums[i % n]while st and num >= nums[st[-1]]:st.pop()if st:ans[i % n] = nums[st[-1]]st.append(i % n)return ans


1475. 商品折扣后的最终价格

给你一个数组 prices ,其中 prices[i] 是商店里第 i 件商品的价格。

商店里正在进行促销活动,如果你要买第 i 件商品,那么你可以得到与 prices[j] 相等的折扣,其中 j 是满足 j > iprices[j] <= prices[i]最小下标 ,如果没有满足条件的 j ,你将没有任何折扣。

请你返回一个数组,数组中第 i 个元素是折扣后你购买商品 i 最终需要支付的价格。

示例 1:

输入:prices = [8,4,6,2,3]
输出:[4,2,4,2,3]
解释:
商品 0 的价格为 price[0]=8 ,你将得到 prices[1]=4 的折扣,所以最终价格为 8 - 4 = 4 。
商品 1 的价格为 price[1]=4 ,你将得到 prices[3]=2 的折扣,所以最终价格为 4 - 2 = 2 。
商品 2 的价格为 price[2]=6 ,你将得到 prices[3]=2 的折扣,所以最终价格为 6 - 2 = 4 。
商品 3 和 4 都没有折扣。

示例 2:

输入:prices = [1,2,3,4,5]
输出:[1,2,3,4,5]
解释:在这个例子中,所有商品都没有折扣。

示例 3:

输入:prices = [10,1,1,6]
输出:[9,0,1,6]

class Solution:def finalPrices(self, prices: List[int]) -> List[int]:st = []ans = prices.copy()# 1.从左到右# for i, x in enumerate(prices):#     while st and x <= prices[st[-1]]:#         j = st.pop()#         ans[j] = prices[j] - x#     st.append(i)# return ans# 2.从右到左for i in range(len(prices) - 1, -1, -1):while st and prices[i] < prices[st[-1]]:st.pop()if st:ans[i] = prices[i] - prices[st[-1]]st.append(i)return ans


901. 股票价格跨度

设计一个算法收集某些股票的每日报价,并返回该股票当日价格的 跨度

当日股票价格的 跨度 被定义为股票价格小于或等于今天价格的最大连续日数(从今天开始往回数,包括今天)。

  • 例如,如果未来 7 天股票的价格是 [100,80,60,70,60,75,85],那么股票跨度将是 [1,1,1,2,1,4,6]

实现 StockSpanner 类:

  • StockSpanner() 初始化类对象。
  • int next(int price) 给出今天的股价 price ,返回该股票当日价格的 跨度

示例:

输入:
["StockSpanner", "next", "next", "next", "next", "next", "next", "next"]
[[], [100], [80], [60], [70], [60], [75], [85]]
输出:
[null, 1, 1, 1, 2, 1, 4, 6]解释:
StockSpanner stockSpanner = new StockSpanner();
stockSpanner.next(100); // 返回 1
stockSpanner.next(80);  // 返回 1
stockSpanner.next(60);  // 返回 1
stockSpanner.next(70);  // 返回 2
stockSpanner.next(60);  // 返回 1
stockSpanner.next(75);  // 返回 4 ,因为截至今天的最后 4 个股价 (包括今天的股价 75) 都小于或等于今天的股价。
stockSpanner.next(85);  // 返回 6

# 往回找小于等于今天价格的连续日期,其实就是找上一个更大元素
class StockSpanner:def __init__(self):self.st = []self.prices = []def next(self, price: int) -> int:self.prices.append(price)# 1. 从左到右# 如果当前元素大于等于栈口元素,那么将栈口元素出栈# 如果当前元素小于栈口元素,那么记录当前元素的答案while self.st and price >= self.prices[self.st[-1]]:# 如果当前股票价格大于栈口元素,那么永远不可能是后面元素的答案,弹出self.st.pop()if self.st:ans = len(self.prices) - self.st[-1] - 1else:# 如果栈没元素了,说明前面的股票都大于等于当前股票ans = len(self.prices)self.st.append(len(self.prices) - 1)return ans# 2.从右到左# 如果当前元素大于栈口元素,说明栈口的元素找到答案了,记录并弹出# 如果当前元素小于等于栈口元素,则进栈# 但由于此题是每天都要返回一次答案,这种思路是只有当当前元素大于栈口元素了,才能返回栈口元素的答案# 所以此题只能按照从右到左的思路# Your StockSpanner object will be instantiated and called as such:
# obj = StockSpanner()
# param_1 = obj.next(price)


1019. 链表中的下一个更大节点

给定一个长度为 n 的链表 head

对于列表中的每个节点,查找下一个 更大节点 的值。也就是说,对于每个节点,找到它旁边的第一个节点的值,这个节点的值 严格大于 它的值。

返回一个整数数组 answer ,其中 answer[i] 是第 i 个节点( 从1开始 )的下一个更大的节点的值。如果第 i 个节点没有下一个更大的节点,设置 answer[i] = 0

示例 1:

img

输入:head = [2,1,5]
输出:[5,5,0]

示例 2:

img

输入:head = [2,7,4,3,5]
输出:[7,0,5,5,0]

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:def nextLargerNodes(self, head: Optional[ListNode]) -> List[int]:st = []     # 栈里面存储的是(下标,节点值)ans = []# 从左到右# 如果当前元素大于栈口元素,说明栈口的元素找到答案了,记录并弹出# 如果当前元素小于等于栈口元素,说明还没有找到答案,进栈while head:ans.append(0)  # 占位while st and head.val > st[-1][1]:j, val = st.pop()ans[j] = head.valst.append((len(ans) - 1, head.val))head = head.nextreturn ans


相关文章:

  • 37、响应处理-【源码分析】-ReturnValueHandler原理
  • 使用API网关Kong配置反向代理和负载均衡
  • Ubuntu20.04 LTS 升级Ubuntu22.04LTS 依赖错误 系统崩溃重装 Ubuntu22.04 LTS
  • CMake指令:string(字符串操作)
  • 渊龙靶场-sql注入(数字型注入)
  • Redis部署架构详解:原理、场景与最佳实践
  • docker使用sh脚本创建容器,保持容器正常运行,异常关闭后马上重启
  • C++哈希表:冲突解决与高效查找
  • 总结:线程安全问题的原因和解决方案
  • 结构化控制语言(SCL) 与梯形图(LAD)相互转换的步骤指南
  • 16QAM在瑞利信道下的性能仿真:从理论到实践的完整解析(附完整代码)
  • PH热榜 | 2025-06-01
  • SpringBoot-Thymeleaf
  • Arch安装botw-save-state
  • Google 发布的全新导航库:Jetpack Navigation 3
  • MySQL中的事务
  • Figma 中构建 Master Control Panel (MCP) 的完整设计方案
  • 【python深度学习】Day43 复习日
  • Go开发简历优化指南
  • ESP-IDF 离线安装——同时存在多个版本以及进行版本切换的方法
  • 微信显示wordpress/seo站点
  • 西部数码网站管理助手 xp/十大教育培训机构排名
  • 个人做网站创业/互联网关键词优化
  • 网站建设需要多少费用/郑州seo代理外包
  • 博客建站程序/网搜网
  • 51ppt模板网官网/邯郸seo排名