xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

Monotonic Stack All In One

Monotonic Stack Data Structure All In One

单调堆栈 数据结构

image

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]


 */

image

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

单调栈:详解与应用

  1. 简介

单调栈(Monotone Stack)是一种特殊类型的栈,其元素满足单调性(递增或递减)。与普通栈相比,单调栈在进出栈操作的基础上,增加了维护单调性的约束。单调栈的操作主要包括:

入栈:将新元素压入栈顶,若新元素破坏了单调性,则需先弹出栈顶元素,直到栈顶元素满足单调性为止。
出栈:弹出栈顶元素。
取栈顶:获取栈顶元素。

  1. 单调栈类型

根据元素的单调方向,单调栈可分为两种类型:

单调递增栈:栈中元素从栈底到栈顶递增排序。
单调递减栈:栈中元素从栈底到栈顶递减排序。

  1. 应用场景

单调栈在算法设计中有着广泛的应用,常见于以下场景:

查找下一个更大/更小元素:例如,求解最近较大的邻居问题(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/)。

  1. 实现与示例

单调栈可以用数组链表实现。以下以单调递增栈为例,使用数组实现:

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

  1. 总结

单调栈是一种简洁高效的数据结构,可用于解决多种算法问题。其核心思想是利用栈的先进后出特性,维护元素的单调性,从而实现高效的查询和操作。在学习和应用单调栈时,应注意其单调性约束对进出栈操作的影响,并结合具体问题进行灵活运用。

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 是一种高效处理特定类型问题的数据结构,特别适合在线性时间复杂度内解决涉及元素顺序的查询问题。理解其工作原理和应用场景可以大大提高解决相关算法问题的效率。

https://chat.openai.com/

refs

https://www.geeksforgeeks.org/introduction-to-monotonic-stack-data-structure-and-algorithm-tutorials/

https://liuzhenglaichn.gitbook.io/algorithm/monotonic-stack

https://medium.com/@florian_algo/introduction-to-monotonic-stack-that-everyone-can-understand-e5f54467faaf



©xgqfrms 2012-2021

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2024-05-27 13:25  xgqfrms  阅读(4)  评论(1编辑  收藏  举报