LeetCode刷题日记2022-3-4/2104. 子数组范围和-单调栈

2104. 子数组范围和

  • 题目描述
  • 题解思路
  • 题解代码

题目描述

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

返回 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

提示:

  • 1 <= nums.length <= 1000
  • -109 <= nums[i] <= 109

题解思路

我们由题目可以知道 如果由m个子数组 那么就有m个子数组的max值-m个子数组的min值

如果我们遍历nums找到nums中每个num出现在各个子数组中 且是其最大值的次数 跟最小值的次数

最大值是要+num 最小值是要-num

我们就能知道每个num对于答案的贡献等于(成为区间最大值的次数-成为区间最小值的次数)*num

  • 成为区间最小值的次数为:
    • 设num的下标为i
    • 在其左侧最近处找到一个小于num的值 并记录其下标为p
    • 在其右侧最近处找到一个小于num的值 并记录其下标为q
    • 则在其区间内可供选择的有(i-p)*(q-i)
  • 成为区间最大值的次数为
    • 设num的下标为i
    • 在其左侧最近处找到一个大于num的值 并记录其下标为p
    • 在其右侧最近处找到一个大于num的值 并记录其下标为q
    • 则在其区间内可供选择的有(i-p)*(q-i)

题解代码

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)

            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]

            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]]

你可能感兴趣的:(Leetcode每日一题,leetcode,算法,python)