2104. 子数组范围和

给你一个整数数组 nums 。nums 中,子数组的 范围 是子数组中最大元素和最小元素的差值。

返回 nums 中 所有 子数组范围的 和 。

子数组是数组中一个连续 非空 的元素序列。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sum-of-subarray-ranges
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

本人写法

class Solution {
    public long subArrayRanges(int[] nums) {
        int n = nums.length;
        long ans = 0;
        for (int i = 0; i < n; i++) {
            int min = nums[i], max = nums[i];
            for (int j = i + 1; j < n; j++) {
                min = Math.min(min, nums[j]);
                max = Math.max(max, nums[j]);
                ans += max - min;
            }
        }
        return ans;
    }
}

大佬补充,单调栈

基础知识1: 设nums[j],nums[k]为nums[i]左右最近的比nums[i]小的值
            则以nums[i]为最小值的子数组共有(i - j) * (k - i)个 (不超过j,k范围且包含i的子数组总数)
            最大值也同理

基础知识2: 子数组的范围和可以表示为所有子数组最大值之和 减去 子数组最小值之和(简单数学推导)

由1、2可知:如果能创建两个数组minLeft和minRight,下标i的值保存基础知识1中j和k的下标
            则(i - minLeft[i]) * (minRight[i] - j)即为以nums[i]为最小值的子数组总数
            用此值再乘以 nums[i] 即可得到nums[i]为最小值的子数组的最小值之和
            对每一个 0 < i < len - 1 做此操作并叠加最小值之和,即可得到整个数组的子数组最小值之和
            最大值同理,由基础知识2即可求得子数组范围和

因此,本题的难点在于:如何构造minLeft和minRight数组(maxLeft, maxRight)

以minLeft为例,利用单调栈构造数组,具体如下:
1. 从左到右遍历nums数组
2. 对于遍历到的nums[i],执行出栈(pop)直到:
    1) 栈空
    2) 栈顶(top)小于nums[i]
此时,可记录minLeft[i]的值为栈顶元素 或 -1 (栈空时),然后将i压入栈中(push)

经此操作,可以构造出minLeft数组;类似也可构造maxLeft,minRight,maxRight

为保证最大值/最小值的唯一性,在出现相同的值时,以下标的大小作为第二判断标准,下标小的认为是更小的值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值