当前位置: 首页 > 知识库问答 >
问题:

使用单调堆栈背后的直觉

濮翰学
2023-03-14

我正在解决leetcode.com上的一个问题:

一个被高度否决的解决方案如下:

class Solution {
public:
  int sumSubarrayMins(vector<int>& A) {
    stack<pair<int, int>> in_stk_p, in_stk_n;
    // left is for the distance to previous less element
    // right is for the distance to next less element
    vector<int> left(A.size()), right(A.size());

    //initialize
    for(int i = 0; i < A.size(); i++) left[i] =  i + 1;
    for(int i = 0; i < A.size(); i++) right[i] = A.size() - i;

    for(int i = 0; i < A.size(); i++){
      // for previous less
      while(!in_stk_p.empty() && in_stk_p.top().first > A[i]) in_stk_p.pop();
      left[i] = in_stk_p.empty()? i + 1: i - in_stk_p.top().second;
      in_stk_p.push({A[i],i});

      // for next less
      while(!in_stk_n.empty() && in_stk_n.top().first > A[i]){
        auto x = in_stk_n.top();in_stk_n.pop();
        right[x.second] = i - x.second;
      }
      in_stk_n.push({A[i], i});
    }

    int ans = 0, mod = 1e9 +7;
    for(int i = 0; i < A.size(); i++){
      ans = (ans + A[i]*left[i]*right[i])%mod;
    }
    return ans;
  }
};

我的问题是:为此使用单调递增的堆栈背后的直觉是什么?它如何帮助计算各种子数组中的最小值?

共有1个答案

池麒
2023-03-14

将数组可视化为线图,将(局部)极小值作为山谷。每个值都与一个范围相关,该范围从上一个较小的值(如果有)之后延伸到下一个较小的值(如果有)之前。(在考虑包含它的单例子数组时,即使是大于其邻居的值也很重要。)变量leftright跟踪该范围。

该堆栈认识到一个值在每个方向上分别阴影了每个大于它的值,因此维护了一个以前未阴影的最小值的列表,用于两个目的:识别新的小数字的范围向后延伸了多远,以及(同时)无效的最小值的范围向前延伸了多远。代码为每个目的使用一个单独的堆栈,但没有必要:在(外部)循环的每次迭代之后,每个堆栈都有相同的内容。

 类似资料:
  • 我的讲师给了我一个任务,创建一个程序,使用堆栈将中缀表达式转换为后缀。我制作了堆栈类和一些函数来读取中缀表达式。 但是这个名为inToPos(charstring[])的函数正在创建断点,该函数负责使用堆栈将字符串中缀中的中缀表达式转换为字符串后缀中的后缀表达式。你们能帮帮我,告诉我我做错了什么吗? 这些是我的代码,非常需要您的帮助:) 注:inToPos功能是使用以下算法实现的: 从左到右扫描中

  • 问题内容: 在Java多线程中,术语和之间在语义上有区别吗? 问题答案: 每个线程都有自己的调用堆栈,“调用堆栈”和“线程堆栈”是同一件事。将其称为“线程堆栈”只是强调了调用堆栈特定于线程。 Bill Venners将此称为Java堆栈: 启动新线程时,Java虚拟机将为该线程创建一个新的Java堆栈。如前所述,Java堆栈将线程的状态存储在离散的帧中。Java虚拟机仅直接在Java堆栈上执行两项

  • 问题内容: 我正在寻找一种在PHP中打印调用堆栈的方法。 如果函数刷新IO缓冲区,则奖励积分。 问题答案: 如果要生成回溯,则正在寻找 和/或 。 例如,第一个将为您提供一个像这样的数组 (引用手册) : 它们显然不会刷新I / O缓冲区,但是您可以使用 和/或自己进行操作 。 (请参阅第一个手册页,以了解为什么使用“和/或” ;-))

  • 我正在为我的一堂计算机科学课开发一个计算后缀表达式结果的程序。该程序使用堆栈ADT来实现这一点。 我已经编写了程序,但相信可能会有错误,因为一些表达式的结果不正确。我不确定我的错误在哪里。 此外,当输入文件为空时,程序将生成一个值32767。那是从哪里来的? 表达式:34+3*值=21。 主程序:

  • 问题内容: 每当调用某个函数时,是否有任何方法可以在C或C ++的运行进程中转储调用堆栈?我想到的是这样的: Where的工作方式与Perl 类似。 或类似这样的东西: 在其中放置某种内部断点,该断点将在每次调用时打印堆栈跟踪。 标准的C库中是否存在类似的东西? 我正在使用GCC在Linux上工作。 背景 我有一个测试运行,该行为基于一些不应影响此行为的命令行开关而有所不同。我的代码有一个伪随机数

  • 我正在解决leetcode.com上的单词搜索问题: 给定一个二维板和一个单词,找出这个单词是否存在于网格中。 我用在线帮助编写的解决方案如下: 我的问题很简单--为什么我们使用回溯方法,而不仅仅是传统的DFS?与我们所做的非常相似,我们可以从每个字符开始,然后进行DFS来确定是否可以找到目标词。但我们没有这样做,为什么? 我对它想了很多,得出了以下推理,但我不确定--我们使用回溯方法,因为同一个