Monotonic Stack All In One
Monotonic Stack Data Structure All In One
单调堆栈
数据结构
errors
function dailyTemperatures(temperatures: number[]): number[] {
let answer = [];
for(let i = 0; i < temperatures.length; i++) {
let flag = false;
let days = 0;
let index = i;
while(index < temperatures.length) {
index += 1;
days += 1;
if(temperatures[index] > temperatures[i]) {
flag = true;
break;
}
}
if(!flag) {
answer[i] = 0;
} else {
answer[i] = days;
}
}
return answer;
};
/*
Time Limit Exceeded
47 / 48 testcases passed
temperatures =
[99,99, 99, ..., 99,99,100]
*/
solutions
function dailyTemperatures(temperatures: number[]): number[] {
let answer = [];
let stack = [];
let count = 0;
for(let i = 0; i < temperatures.length; i++) {
// 小顶栈, 递减
// 大顶栈, 递增
while(stack.length && temperatures[stack[stack.length - 1]] < temperatures[i]) {
let index = stack.pop();
answer[index] = i - index;
// console.log(`count`, ++count);
}
stack.push(i);
}
// 补 0
// console.log(`stack =`, stack);
while(stack.length) {
let index = stack.pop();
answer[index] = 0;
}
return answer;
};
demos
function dailyTemperatures(temperatures: number[]): number[] {
// ❌ error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
// let answer = [...``.padEnd(temperatures.length, 0)].map(Number);
// let answer = [...``.padEnd(temperatures.length, 0)].map(i => parseInt(i))!;
let answer = [];
// let answer = new Array(temperatures.length).fill(0);
let stack = [];
let count = 0;
for(let i = 0; i < temperatures.length; i++) {
// 小顶栈, 递减
// 大顶栈, 递增
while(stack.length && temperatures[stack[stack.length - 1]] < temperatures[i]) {
let index = stack.pop();
answer[index] = i - index;
console.log(`count`, ++count);
}
// while(stack.length) {
// if(temperatures[stack[stack.length - 1]] < temperatures[i]) {
// // console.log(`index, i =`, index, i);
// // console.log(`✅i - index =`, i - index);
// let index = stack.pop();
// answer[index] = i - index;
// } else {
// // let index = stack.pop();
// // answer[index] = 0;
// }
// console.log(`count`, ++count);
// }
stack.push(i);
// console.log(`stack, i =`, stack, i);
}
// 补 0
console.log(`stack =`, stack);
while(stack.length) {
let index = stack.pop();
answer[index] = 0;
}
return answer;
};
/*
构造数据,测试循环次数 ?0 day 如何优雅的处理
// 最好 循环次数
[31,33,35,37,39]
// 最坏 循环次数
[39,37,35,33,31]
*/
function dailyTemperatures(temperatures: number[]): number[] {
// ❌ error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
// let answer = [...``.padEnd(temperatures.length, 0)].map(Number);
// let answer = [...``.padEnd(temperatures.length, 0)].map(i => parseInt(i))!;
// let answer = [];
let answer = new Array(temperatures.length).fill(0);
let stack = [];
for(let i = 0; i < temperatures.length; i++) {
// 小顶栈, 递减
// 大顶栈, 递增
while(stack.length && temperatures[stack[stack.length - 1]] < temperatures[i]) {
let index = stack.pop();
// console.log(`index, i =`, index, i);
// console.log(`✅i - index =`, i - index);
answer[index] = i - index;
}
stack.push(i);
// console.log(`stack, i =`, stack, i);
}
return answer;
};
https://leetcode.com/problems/daily-temperatures/?envType=study-plan-v2&envId=leetcode-75
https://leetcode.com/problems/online-stock-span/description/?envType=study-plan-v2&envId=leetcode-75
(🐞 反爬虫测试!打击盗版⚠️)如果你看到这个信息, 说明这是一篇剽窃的文章,请访问 https://www.cnblogs.com/xgqfrms/ 查看原创文章!
LeetCode 75
Ace Coding Interview with 75 Qs
https://leetcode.com/studyplan/leetcode-75/
AI
prompt =
作为一名编程技术专家,请详细解释什么是 Monotonic Stack
单调栈:详解与应用
- 简介
单调栈(Monotone Stack)是一种特殊类型的栈,其元素满足单调性
(递增或递减)。与普通栈相比,单调栈在进出栈操作的基础上,增加了维护单调性的约束
。单调栈的操作主要包括:
入栈:将新元素压入栈顶,若新元素破坏了单调性,则需先弹出栈顶元素,直到栈顶元素满足单调性为止。
出栈:弹出栈顶元素。
取栈顶:获取栈顶元素。
- 单调栈类型
根据元素的单调方向,单调栈可分为两种类型:
单调递增栈:栈中元素从栈底到栈顶递增排序。
单调递减栈:栈中元素从栈底到栈顶递减排序。
- 应用场景
单调栈在算法设计中有着广泛的应用,常见于以下场景:
查找下一个更大/更小元素:例如,求解最近较大的邻居问题(https://leetcode.com/problems/next-greater-element-i/)。
计算矩形面积:例如,求解最大矩形面积问题(https://walkccc.me/LeetCode/problems/85/)。
验证字符串匹配:例如,验证括号是否有效(https://leetcode.com/problems/valid-parentheses/)。
滑动窗口问题:例如,求解滑动窗口最大值问题(https://leetcode.com/problems/sliding-window-maximum/description/)。
- 实现与示例
单调栈可以用数组
或链表
实现。以下以单调递增栈为例,使用数组实现:
class MonotonicStack:
def __init__(self):
self.stack = []
def push(self, element):
while self.stack and self.stack[-1] > element:
self.stack.pop()
self.stack.append(element)
def pop(self):
if self.stack:
return self.stack.pop()
return None
def top(self):
if self.stack:
return self.stack[-1]
return None
# 测试用例
stack = MonotonicStack()
stack.push(3)
stack.push(5)
stack.push(2)
stack.push(1)
stack.push(4)
print(stack.pop()) # 输出:4
print(stack.pop()) # 输出:1
print(stack.top()) # 输出:2
- 总结
单调栈是一种简洁高效的数据结构,可用于解决多种算法问题。其核心思想是利用栈的先进后出特性,维护元素的单调性,从而实现高效的查询和操作。在学习和应用单调栈时,应注意其单调性约束对进出栈操作的影响,并结合具体问题进行灵活运用。
https://gemini.google.com/app/
https://gemini.google.com/app/5d624a82c2acf4ad
https://g.co/gemini/share/a9966458b2b8
作为一名编程技术专家,我很高兴为您解释什么是 Monotonic Stack。
Monotonic Stack 是一种特殊的数据结构,它可以用来解决一些常见的算法问题,如寻找数组中的最大/最小元素、寻找数组中的下一个更大/更小元素等。
Monotonic Stack 的特点是:
栈中元素是单调递增或单调递减的。
栈顶元素始终是当前栈中最大或最小的元素。
Monotonic Stack 的工作原理如下:
我们从左到右遍历数组。
对于每个元素,我们将其与栈顶元素进行比较:
如果当前元素小于(或大于)栈顶元素,则将其推入栈中。
如果当前元素大于(或小于)栈顶元素,则不断弹出栈顶元素,直到找到一个小于(或大于)当前元素的元素为止,然后将当前元素推入栈中。
这样,我们就可以在 O(n) 的时间复杂度内解决上述问题。
Monotonic Stack 的典型应用包括:
寻找数组中的下一个更大/更小元素。
寻找数组中的最大/最小元素。
计算数组中元素的 Span (一个元素到它左边第一个比它小/大的元素的距离)。
在柱状图中寻找最大矩形面积。
总之,Monotonic Stack 是一种非常有用的数据结构,可以帮助我们高效地解决一些常见的算法问题。希望这个解释对您有所帮助。如果您还有任何其他问题,欢迎随时询问。
https://duckduckgo.com/?q=DuckDuckGo&ia=chat
Monotonic Stack 是一种特殊的栈数据结构,常用于解决一类涉及到元素顺序、区间最大最小值等问题。其核心特性是栈内的元素按某种单调顺序排列,即每次向栈中压入新元素时,都会保证栈内的元素按某种顺序单调递增或单调递减。具体来说,Monotonic Stack 可以分为两种类型:
单调递增栈(Monotonic Increasing Stack):栈内元素从栈底到栈顶单调递增。
单调递减栈(Monotonic Decreasing Stack):栈内元素从栈底到栈顶单调递减。
主要特点
保证单调性:每次压入一个新元素时,会从栈顶开始弹出不满足单调性的元素,直到剩下的元素符合单调性要求。
适用场景广泛:特别适用于解决需要维护一个滑动窗口的最小值或最大值的问题,或在数组中找到下一个更大或更小元素的问题。
使用场景
Next Greater Element:找出数组中每个元素右边第一个比它大的元素。
Next Smaller Element:找出数组中每个元素右边第一个比它小的元素。
滑动窗口最小值/最大值:在一个固定大小的滑动窗口内,快速找到最小值或最大值。
直方图中的最大矩形:找出给定直方图中最大的矩形面积。
工作原理
以单调递增栈为例,当处理数组时,保证栈内元素单调递增的步骤如下:
初始化空栈。
遍历数组:对于当前元素 arr[i]:
如果栈非空且 arr[i] 小于或等于栈顶元素,则不断弹出栈顶元素,直到栈顶元素小于 arr[i] 或栈为空。
将 arr[i] 压入栈中。
重复上述步骤,直到遍历完整个数组。
这样在任何时刻,栈内元素总是从底到顶单调递增。
示例代码
以下是一个使用单调递增栈来解决“下一个更大元素”的示例代码:
def next_greater_elements(nums):
n = len(nums)
res = [-1] * n
stack = []
for i in range(n):
while stack and nums[stack[-1]] < nums[i]:
index = stack.pop()
res[index] = nums[i]
stack.append(i)
return res
# 测试
nums = [2, 1, 2, 4, 3]
print(next_greater_elements(nums)) # 输出: [4, 2, 4, -1, -1]
在这个示例中,我们使用一个单调递增栈来存储元素的索引。对于每个元素 nums[i],我们从栈顶弹出所有小于 nums[i] 的元素,这些元素的下一个更大元素就是 nums[i]。最后,将当前元素的索引压入栈中。
总结
Monotonic Stack 是一种高效处理特定类型问题的数据结构,特别适合在线性时间复杂度内解决涉及元素顺序的查询问题。理解其工作原理和应用场景可以大大提高解决相关算法问题的效率。
refs
https://liuzhenglaichn.gitbook.io/algorithm/monotonic-stack
©xgqfrms 2012-2021
www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!
原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/18215307
未经授权禁止转载,违者必究!