LeetCode 2104. 子数组范围和

208 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

给你一个整数数组 nums 。nums 中,子数组的 范围 是子数组中最大元素和最小元素的差值。返回 nums 中 所有 子数组范围的 和 。子数组是数组中一个连续 非空 的元素序列。

此题我们可以采用暴力枚举,就是把所有子数组的可能全部列举出来,并求出每个子数组中最大值与最小值的差,最后相加得到结果。

举个例子:

[4, -2, -3, 4, 1]

对于这个数组,它有如下几种子数组:

  1. 1个元素的子数组:[4]、[-2]、[-3]、[4]、[1]
  2. 2个元素的子数组:[4,-2]、[-2,-3]、[-3,4]、[4,1]
  3. 3个元素的子数组:[4,-2,-3]、[-2,-3,4]、[-3,4,1]
  4. 4个元素的子数组:[4,-2,-3,4]、[-2,-3,4,1]
  5. 5个元素的子数组:[4,-2,-3,4,1]

那么如何枚举也是一个问题,我们可以从数组的第一个元素开始,不断地往后扩展子数组的长度,以此进行遍历,如下图所示:

image.png

我们可以定义两个指针left和right,其中left为子数组的左边界,right为子数组的右边界,通过left和right指针能够确定一个子数组,同时记录这个子数组中的最大值和最小值,得到差并计算结果。

代码如下:

public static long subArrayRanges(int[] nums) {
    long result = 0;
    // 定义左边界
    for (int left = 0; left < nums.length; ++left) {
        int min = Integer.MAX_VALUE;
        int max = Integer.MIN_VALUE;
        // 定义右边界
        for (int right = left; right < nums.length; ++right) {
            // 记录最大值与最小值
            // 如果新添进子数组的元素不大于最大值,不小于最小值,则仍然会使用前面记录的最大值与最小值
            min = Math.min(min, nums[right]);
            max = Math.max(max, nums[right]);
            // 计算结果
            result += max - min;
        }
    }
    return result;
}