第十章 单调栈 Part1
任务
739. 每日温度
给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。
思路
使用单调栈来解决这种类型的问题(右边第一个比我大(小)的值)
需要注意的点为,栈中存放的是索引,比较时比较的是值,容易粗心出错。注意将处理完的栈顶节点弹出,以及处理完一轮弹出循环后,需要将当前这个比较节点加入到栈中,最后这个比较容易遗漏。这里是根据题意收集结果后弹出,实际上即使不收集结果或者是在特殊条件下收集结果,弹出的流程也是根据单调栈的处理流程来的(维护单调栈本身的结构),而不是收集结果后直接弹出的,这点需要注意,即只要满足 len(stack) > 0 and temperatures[i] > temperatures[stack[-1]] 条件就弹出,可以参考下一题。
class Solution: def dailyTemperatures(self, temperatures: List[int]) -> List[int]: stack = [] result = [0] * len(temperatures) for i in range(len(temperatures)): if len(stack) > 0 and temperatures[i] <= temperatures[stack[-1]]: stack.append(i) else: while len(stack) > 0 and temperatures[i] > temperatures[stack[-1]]: result[stack[-1]] = i - stack[-1] stack.pop() stack.append(i) return result
另外,上面的代码可以简化,但是为了逻辑的清晰,后续单调栈的题还是先按照上面的相对麻烦的写法来。
class Solution: def dailyTemperatures(self, temperatures: List[int]) -> List[int]: stack = [] result = [0] * len(temperatures) for i in range(len(temperatures)): while len(stack) > 0 and temperatures[i] > temperatures[stack[-1]]: result[stack[-1]] = i - stack[-1] stack.pop() stack.append(i) return result
496. 下一个更大元素 I
nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。
给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。
对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j] 的 下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1 。
返回一个长度为 nums1.length 的数组 ans 作为答案,满足 ans[i] 是如上所述的 下一个更大元素 。
思路
实际就是上一题的变形,只要理解了单调栈的本体逻辑,这题是在特殊情况下收集结果,而为了维持单调栈本身的结构和流程,需要注意弹出的时机。
class Solution: def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]: stack = [] result = [-1] * len(nums1) for i in range(len(nums2)): if len(stack)>0 and 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: result[nums1.index(nums2[stack[-1]])] = nums2[i] stack.pop() stack.append(i) return result
503. 下一个更大元素 II
给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。
数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1 。
思路
这题看似比较简单,将之前的普通数组改为了循环数组,会直接想到用取模。但实际上深入思考后,发现之所以result[i]没有被后续覆盖的,是因为后续(第二轮)不会进入到给result[i]赋值的条件内。
这道题的理解起来简单的思路是复制一份扩展为2倍的数组,这是完全符合题意的,但是编码还是用取模比较简洁和省空间。
class Solution: def nextGreaterElements(self, nums: List[int]) -> List[int]: stack = [] result = [-1] * len(nums) for i in range(2 * len(nums)): reali = i % len(nums) if len(stack) > 0 and nums[reali] <= nums[stack[-1]]: stack.append(reali) else: while len(stack) > 0 and nums[reali] > nums[stack[-1]]: result[stack[-1]] = nums[reali] stack.pop() stack.append(reali) return result
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构