LeetCode 907: 子数组的最小值之和-单调栈的运用 |Sum of Subarray Minimums-Fantasy use of Monotonic Stack

Tags: #MonoStack #Stack

Problem Description

Given an array of integers arr, find the sum of min(b), where b ranges over every (contiguous) subarray of arr. Module the answer (10^9+7).

Example:

Input: arr = [3,1,2,4]
Output: 17
Explanation:
Subarrays are [3], [1], [2], [4], [3,1], [1,2], [2,4], [3,1,2], [1,2,4], [3,1,2,4].

Minimums are 3, 1, 2, 4, 1, 1, 2, 1, 1, 1.

Sum is 17.

Problem Analysis & Transformation

We are asked to get each subarray’s min, and sum them up. The straightforward way is to calculate the minimum value of each subarray, and sum them up.

We can transform this question to another one. For each element i(i is the index), find the number of subarrays whose minimum element is that element, mark as #i.

In the above example:
#0=1, the range is [3], the subarray is [3].
#1=6, the range is [3,1,2,4], those subarrays are [3,1], [1], [1,2], [1,2,4], [3,1,2], [3,1,2,4].
#2=2, the range is [2,4], those subarrays are [2], [2,4].
#3=1, the range is [4], the subarray is [4].

So the total sum is each element’s value times the number of subarrays it corresponding to. totalSum=sum(arr[i]*#i).
totalSum=1*3+6*1+2*2+4*1=17

If there are two same elements, they will find same subarrays. We deal with this situation as follows:
Every element’s subarrays’ left edge is the first element that small or equal to it(if there is none, mark as -1), the right edge is the first element that strictly less than it(if non, mark as n: length of arr).

Here is an example:
arr = [3,1,5,1,2,4]
The subarray range of the right 1([3,1,5,_1_,2,4]) is [1,2,4]. The subarray range of the left 1([3,_1_,5,1,2,4]) is [3,1,5,1,2,4]. So that those two 1’s subarrays won’t be intersected.

So the method to find subarray range is:

Given an element e, find the first element less than or equal to e to the left as the left boundary, and the first element strictly less than e to the right as the right boundary. The range does not contain boundaries.

The proof maybe incomplete…
The proof is divided into two aspects:

If there is a subarray sArr that is not contained. Assume the minimum element of sArr is e. In the find subarray step, all subarray which has no element small than e should be found. That’s a contradiction. Even there are two same elements in sArr, at least one has contained this subarray.

Assume there is a subarray sArr which is found by two different element e and v(different in index, may same in value).

Case 1: e!=v
Since e=min(sArr) and v=min(sArr), so e=v, that’s a contradiction.

Case 2: e=v
As explained in above boundary situation, as index of e is not equal to v, w.o.l.g, assume index of e is smaller than index of v. So the range of e‘s subarray should be [..e..v...], while the range of v‘s subarray should be [..v...] which does contain element e and even left. So e and v won’t find a same subarray(because the subarray range is different).

In last part, we find the subarray range of an elements e, where each element in the subarray is equal or bigger than e.

So the problem comes: How to count the number of the subarrays of that range?

It’s quite easy. The left side elements number is idx(e)-leftBound, they can form idx(e)-leftBound subarrays(remember subarray must contain e). The right side elements number is rightBound-idx(e), they can form rightBound-idx(e) subarrays. The left and right sides are combined in pairs to produce all subarrays: #idx(e)=(idx(e)-leftBound)*(rightBound-idx(e)).

So the answer is totalSum=sum(arr[i]*#i).

Review of problem transformation process

To find next smaller value, use mono-stack!

Coding Details

We need to find the first element less than or equal to each element to the left, and the first element strictly less than each element to the right. Problem like this, finding the one-side small, should be solved using monotonic stack.

We can use an increasing stack, when pushing an element, popping until the peek element of the stack is smaller than or equal to the pushing element. Every popped element’s right side is also determined, just like Largest Rectangle in Histogram previous blog.

When popping an element, we know it’s left bound, the peek element of stack, we also know it’s right bound, the pushing element. So we add its contribution to the answer.

The answer maybe quite large, so we need to module (10^9+7) when calculating.

Since there may be no smaller element in left, so we set it to -1. Same as the right side, set it to n.

In the pushing process, we also push -1 and n to the stack, the value corresponding to it is infinitesimal. We pushing -1 first because every element are larger than it, so it can be proper boundary when popping. We pushing n finally because every element are also larger than it(except the first -1), so when pushing n, all elements of arr will be popped out, and their right boundary are n. That’s understandable, because when pushing n, there is only a monotonically increasing sequence left in the stack.

The code as follows:

public class Solution {
    int[] arr;
    int n;

    public int sumSubarrayMins(int[] arr) {
        int MOD = 1_000_000_007;

        // handle input arr's error
        if (arr == null || arr.length == 0) {
            return 0;
        }
        this.arr = arr;
        n = arr.length;

        long ans = 0L;
        Deque increStack = new ArrayDeque<>();
        // add index -1 and n into the process(their value are minInfinity) so that
        // don't need to consider boundary situation.

        for (int i = -1; i

Original: https://www.cnblogs.com/liuzhch1/p/16421111.html
Author: liuzhch1
Title: LeetCode 907: 子数组的最小值之和-单调栈的运用 |Sum of Subarray Minimums-Fantasy use of Monotonic Stack

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/606694/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • ThinkPHP5浏览器关闭,继续执行php脚本

    ignore_user_abort(); //即使Client断开(如关掉浏览器),PHP脚本也可以继续执行. set_time_limit(0); //执行时间为无限制,php默…

    Linux 2023年6月7日
    088
  • 常见题目

    这几天有朋友反映给小编说让多发点关于面试的文章,小编深知从事IT行业的难处,跳槽多,加班多,薪资不乐观,大多数朋友都想找新的工作,进入一个好的公司,今天小编就给大家带来了C语言面试…

    Linux 2023年6月13日
    093
  • Java基础系列–03_Java中的方法描述

    Java的方法(函数)的描述 方法(1)方法的定义:就是完成特定功能的代码块。注意:在很多语言里面有函数的定义,而在Java中,函数被称为方法。(2)格式:修饰符 返回值类型 方法…

    Linux 2023年6月7日
    0107
  • 翻车!误删/usr/lib/引发的血案,从棺材边成功抢救的过程分享。

    写在开篇 血案:本地开发机是CentOS 7,本想删除在/usr/lib/下的一个软链,如:/usr/lib/xxx。当正想删除时,突然被别的事情打扰了一下,回过神之后莫名奇妙的执…

    Linux 2023年6月7日
    094
  • 国产化之x64平台安装银河麒麟操作系统

    背景 某个项目需要实现基础软件全部国产化,其中操作系统指定银河麒麟v4,CPU使用飞腾处理器。飞腾处理器是ARMv8架构的,在之前的文章中介绍了使用QEMU模拟ARMv8架构安装银…

    Linux 2023年5月27日
    081
  • bootstrap的基础使用

    Bootstrap Bootstrap是Twitter推出的一个用于前端开发的开源工具包。它由Twitter的设计师Mark Otto和Jacob Thornton合作开发,是一个…

    Linux 2023年6月7日
    0104
  • 同城双活概述

    引言 同城双活,是年度最大的架构变更。同城容灾,对于生产的高可用保障,重大的意义和价值是不言而喻的。 用储总的话说,这么重要的架构工作,所有架构师都应该重点主导和参与。 同城双活,…

    Linux 2023年6月14日
    0118
  • uniapp使用阿里云矢量图标库,h5端显示正常,真机app不显示问题解决

    1、在阿里云矢量图标库网站管理界面如上图,首先下载至本地1的位置,然后在2的位置复制代码 2、在下图中static目录下放入下载的iconfont.css文件,并且修改里面的链接,…

    Linux 2023年6月7日
    093
  • 文本编辑命令

    一、vim编辑器 1、vim的三种模式 一般模式(正常模式):以vim打开文件就直接进入到此模式,此模式中可以使用上下左右按键进行移动光标,也可以在此模式下进行文件的复制粘贴删除等…

    Linux 2023年6月6日
    0106
  • 记录XorDDos木马清理步骤

    1.检查 查看定时任务文件发现有两个异常定时任务 [root@manage ~]# cat /etc/crontab user-name command to be execute…

    Linux 2023年6月7日
    093
  • Ruby快速入门

    推荐网站:http://ruby-for-beginners.rubymonstas.org/index.html源码参考:https://gitee.com/komavideo/…

    Linux 2023年6月14日
    095
  • 模糊测试基本概念FuzzTest

    1. what is FUZZ TESTing? Fuzz Testing is an automated software testing technology, origina…

    Linux 2023年6月7日
    071
  • 使用 Spring Boot Admin 监控应用状态

    1 Spring Boot Actuator Spring Boot Actuator 是 Spring Boot 提供的对应用的自省和监控功能,如健康检查,审计,指标收集,HTT…

    Linux 2023年6月7日
    093
  • 趣谈IO多路复用的本质

    在《轻松搞懂5种IO模型》中,我发起了一个投票。 答案是【同步IO多路复用】。目前,60%的朋友答对了。原因这里解释一下。 同步和异步的概念区别 同步:线程自己去获取结果。(一个线…

    Linux 2023年6月14日
    099
  • POJ3071(Football)–概率DP

    题意:有(1< en….网上当然也后不少解题报告,但是很多直接给出状态转移方程和贴出代码,而少了其中重要的推断过程,我觉得不是很好。所以自己给写一个较为详细的过程…

    Linux 2023年6月7日
    0103
  • 如何获取 Docker 容器的 IP 地址

    查询单个容器 IP 地址: 使用下面命令可以查看容器详细信息,里面包含 IP 地址信息: docker inspect <container id> </cont…

    Linux 2023年6月7日
    089
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球