列表

详情


2104. 子数组范围和

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

返回 nums所有 子数组范围的

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

 

示例 1:

输入:nums = [1,2,3]
输出:4
解释:nums 的 6 个子数组如下所示:
[1],范围 = 最大 - 最小 = 1 - 1 = 0 
[2],范围 = 2 - 2 = 0
[3],范围 = 3 - 3 = 0
[1,2],范围 = 2 - 1 = 1
[2,3],范围 = 3 - 2 = 1
[1,2,3],范围 = 3 - 1 = 2
所有范围的和是 0 + 0 + 0 + 1 + 1 + 2 = 4

示例 2:

输入:nums = [1,3,3]
输出:4
解释:nums 的 6 个子数组如下所示:
[1],范围 = 最大 - 最小 = 1 - 1 = 0
[3],范围 = 3 - 3 = 0
[3],范围 = 3 - 3 = 0
[1,3],范围 = 3 - 1 = 2
[3,3],范围 = 3 - 3 = 0
[1,3,3],范围 = 3 - 1 = 2
所有范围的和是 0 + 0 + 0 + 2 + 0 + 2 = 4

示例 3:

输入:nums = [4,-2,-3,4,1]
输出:59
解释:nums 中所有子数组范围的和是 59

 

提示:

 

进阶:你可以设计一种时间复杂度为 O(n) 的解决方案吗?

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: long long subArrayRanges(vector<int>& nums) { } };

python3 解法, 执行用时: 76 ms, 内存消耗: 15.1 MB, 提交时间: 2022-11-29 11:58:51

class Solution:
    def subArrayRanges(self, nums: List[int]) -> int:
        n = len(nums)
        minLeft, maxLeft = [0] * n, [0] * n
        minStack, maxStack = [], []
        for i, num in enumerate(nums):
            while minStack and nums[minStack[-1]] > num:
                minStack.pop()
            minLeft[i] = minStack[-1] if minStack else -1
            minStack.append(i)

            # 如果 nums[maxStack[-1]] == num, 那么根据定义,
            # nums[maxStack[-1]] 逻辑上小于 num,因为 maxStack[-1] < i
            while maxStack and nums[maxStack[-1]] <= num:
                maxStack.pop()
            maxLeft[i] = maxStack[-1] if maxStack else -1
            maxStack.append(i)

        minRight, maxRight = [0] * n, [0] * n
        minStack, maxStack = [], []
        for i in range(n - 1, -1, -1):
            num = nums[i]
            # 如果 nums[minStack[-1]] == num, 那么根据定义,
            # nums[minStack[-1]] 逻辑上大于 num,因为 minStack[-1] > i
            while minStack and nums[minStack[-1]] >= num:
                minStack.pop()
            minRight[i] = minStack[-1] if minStack else n
            minStack.append(i)

            while maxStack and nums[maxStack[-1]] < num:
                maxStack.pop()
            maxRight[i] = maxStack[-1] if maxStack else n
            maxStack.append(i)

        sumMax, sumMin = 0, 0
        for i, num in enumerate(nums):
            sumMax += (maxRight[i] - i) * (i - maxLeft[i]) * num
            sumMin += (minRight[i] - i) * (i - minLeft[i]) * num
        return sumMax - sumMin

javascript 解法, 执行用时: 80 ms, 内存消耗: 46.8 MB, 提交时间: 2022-11-29 11:58:30

/**
 * @param {number[]} nums
 * @return {number}
 */
var subArrayRanges = function(nums) {
    const n = nums.length;
    const minLeft = new Array(n).fill(0);
    const minRight = new Array(n).fill(0);
    const maxLeft = new Array(n).fill(0);
    const maxRight = new Array(n).fill(0);
    let minStack = [];
    let maxStack = [];
    for (let i = 0; i < n; i++) {
        while (minStack.length && nums[minStack[minStack.length - 1]] > nums[i]) {
            minStack.pop();
        }
        minLeft[i] = minStack.length === 0 ? -1 : minStack[minStack.length - 1];
        minStack.push(i);
        
        // 如果 nums[maxStack[maxStack.length - 1]] == nums[i], 那么根据定义,
        // nums[maxStack[maxStack.length - 1]] 逻辑上小于 nums[i],因为 maxStack[maxStack.length - 1] < i
        while (maxStack.length && nums[maxStack[maxStack.length - 1]] <= nums[i]) { 
            maxStack.pop();
        }
        maxLeft[i] = maxStack.length === 0 ? -1 : maxStack[maxStack.length - 1];
        maxStack.push(i);
    }
    minStack = [];
    maxStack = [];
    for (let i = n - 1; i >= 0; i--) {
        // 如果 nums[minStack[minStack.length - 1]] == nums[i], 那么根据定义,
        // nums[minStack[minStack.length - 1]] 逻辑上大于 nums[i],因为 minStack[minStack.length - 1] > i
        while (minStack.length && nums[minStack[minStack.length - 1]] >= nums[i]) { 
            minStack.pop();
        }
        minRight[i] = minStack.length === 0 ? n : minStack[minStack.length - 1];
        minStack.push(i);

        while (maxStack.length && nums[maxStack[maxStack.length - 1]] < nums[i]) {
            maxStack.pop();
        }
        maxRight[i] = maxStack.length === 0 ? n : maxStack[maxStack.length - 1];
        maxStack.push(i);
    }

    let sumMax = 0, sumMin = 0;
    for (let i = 0; i < n; i++) {
        sumMax += (maxRight[i] - i) * (i - maxLeft[i]) * nums[i];
        sumMin += (minRight[i] - i) * (i - minLeft[i]) * nums[i];
    }
    return sumMax - sumMin;
};

golang 解法, 执行用时: 4 ms, 内存消耗: 5.2 MB, 提交时间: 2022-11-29 11:57:55

func subArrayRanges(nums []int) int64 {
    n := len(nums)
    minLeft := make([]int, n)
    maxLeft := make([]int, n)
    var minStk, maxStk []int
    for i, num := range nums {
        for len(minStk) > 0 && nums[minStk[len(minStk)-1]] > num {
            minStk = minStk[:len(minStk)-1]
        }
        if len(minStk) > 0 {
            minLeft[i] = minStk[len(minStk)-1]
        } else {
            minLeft[i] = -1
        }
        minStk = append(minStk, i)

        // 如果 nums[maxStk[len(maxStk)-1]] == num, 那么根据定义,
        // nums[maxStk[len(maxStk)-1]] 逻辑上小于 num,因为 maxStk[len(maxStk)-1] < i
        for len(maxStk) > 0 && nums[maxStk[len(maxStk)-1]] <= num {
            maxStk = maxStk[:len(maxStk)-1]
        }
        if len(maxStk) > 0 {
            maxLeft[i] = maxStk[len(maxStk)-1]
        } else {
            maxLeft[i] = -1
        }
        maxStk = append(maxStk, i)
    }

    minRight := make([]int, n)
    maxRight := make([]int, n)
    minStk = minStk[:0]
    maxStk = maxStk[:0]
    for i := n - 1; i >= 0; i-- {
        num := nums[i]
        // 如果 nums[minStk[len(minStk)-1]] == num, 那么根据定义,
        // nums[minStk[len(minStk)-1]] 逻辑上大于 num,因为 minStk[len(minStk)-1] > i
        for len(minStk) > 0 && nums[minStk[len(minStk)-1]] >= num {
            minStk = minStk[:len(minStk)-1]
        }
        if len(minStk) > 0 {
            minRight[i] = minStk[len(minStk)-1]
        } else {
            minRight[i] = n
        }
        minStk = append(minStk, i)

        for len(maxStk) > 0 && nums[maxStk[len(maxStk)-1]] < num {
            maxStk = maxStk[:len(maxStk)-1]
        }
        if len(maxStk) > 0 {
            maxRight[i] = maxStk[len(maxStk)-1]
        } else {
            maxRight[i] = n
        }
        maxStk = append(maxStk, i)
    }

    var sumMax, sumMin int64
    for i, num := range nums {
        sumMax += int64(maxRight[i]-i) * int64(i-maxLeft[i]) * int64(num)
        sumMin += int64(minRight[i]-i) * int64(i-minLeft[i]) * int64(num)
    }
    return sumMax - sumMin
}

golang 解法, 执行用时: 20 ms, 内存消耗: 4.1 MB, 提交时间: 2022-11-29 11:57:36

func subArrayRanges(nums []int) (ans int64) {
    for i, num := range nums {
        minVal, maxVal := num, num
        for _, v := range nums[i+1:] {
            if v < minVal {
                minVal = v
            } else if v > maxVal {
                maxVal = v
            }
            ans += int64(maxVal - minVal)
        }
    }
    return
}

javascript 解法, 执行用时: 92 ms, 内存消耗: 41.5 MB, 提交时间: 2022-11-29 11:57:20

/**
 * @param {number[]} nums
 * @return {number}
 */
var subArrayRanges = function(nums) {
    const n = nums.length;
    let ret = 0;
    for (let i = 0; i < n; i++) {
        let minVal = Number.MAX_VALUE, maxVal = -Number.MAX_VALUE;
        for (let j = i; j < n; j++) {
            minVal = Math.min(minVal, nums[j]);
            maxVal = Math.max(maxVal, nums[j]);
            ret += maxVal - minVal;
        }
    }
    return ret;
};

python3 解法, 执行用时: 3780 ms, 内存消耗: 14.9 MB, 提交时间: 2022-11-29 11:56:35

class Solution:
    def subArrayRanges(self, nums: List[int]) -> int:
        ans, n = 0, len(nums)
        for i in range(n):
            minVal, maxVal = inf, -inf
            for j in range(i, n):
                minVal = min(minVal, nums[j])
                maxVal = max(maxVal, nums[j])
                ans += maxVal - minVal
        return ans

上一题