子数组的最小值之和

题目分析
给定一个数组A,求该数组的所有连续子数组的最小值的总和。

举个例子:比如A=[3,1,2,4],所有连续子数组分别为 [3],[1],[2],[4],[3,1],[1,2],[2,4],[3,1,2],[1,2,4],[3,1,2,4],对应子数组的最小值分别为3,1,2,4,1,1,2,1,1,1,总和为17。
链接:https://leetcode.cn/problems/sum-of-subarray-minimums/solution/xiao-bai-lang-dong-hua-xiang-jie-bao-zhe-489q/
来源:力扣(LeetCode)

解题思路:

最小值是在一段连续数字中被筛选出来的,也就是说每个最小值都有一定的辐射范围。假设给定数组A=[3,1,2,4,1],在一段连续数字3、1、2、4、1中,只要其中一段数字包含1,那么这段数字的最小值肯定为1,例如[3,1,2,4,1]、[3,1,2,4]、[3,1,2]、[1,2]等最小值都为1,我们把这叫做元素1的辐射范围。

假设辐射范围的左边界为left,右边界为right,元素E的下标为i,那么子数组的左边界应该在[left,i]中选取,子数组的右边界应该在[i,right]中选取。因此子数组个数为(i - left + 1) * (right - i + 1)(i−left+1)∗(right−i+1),也就是说元素A[i]对答案的总贡献值为A[i]*(i - left + 1) * (right - i + 1)A[i]∗(i−left+1)∗(right−i+1)。

代码:(Java)

public static class Solution {
		private static final int mod =1000000007;
	    public int sumSubarrayMins(int[] arr) {
	    	if(arr==null||arr.length==0) {
	    		return 0;
	    	}
	    int n = arr.length;
	    int left[]  = new int[n];
	    int right[] = new int[n];
	    Deque<Integer> stack = new LinkedList<Integer>();
	    
	    //求左边界
	    for(int i=0;i<n;i++) {//左边栈中一般存放的是当前第一小的与第二小的
	    	while(!stack.isEmpty()&&arr[stack.peek()]>arr[i]) {
	    		stack.pop();  //找到左边比当前数更小的,大的都出栈
	    	}
	    	if(stack.isEmpty()) {//设置边界,左边没有更小的就设为-1
	    		left[i] = -1;
	    	}else {
				left[i] = stack.peek();//找到更小的
			}
	    	stack.push(i);  	//将当前值放入栈,方便得到i与arr[i]
	    }
	    
	    stack.clear();//清空栈
	    for(int i =n-1;i>=0;i--) {
	    	//System.out.println(stack.size());
	    	while(!stack.isEmpty()&&arr[stack.peek()]>=arr[i]) {
	    		stack.pop();
	    	}
	    	if(stack.isEmpty()) {
	    		right[i] =n;
	    	}else {
				right[i] =stack.peek();
			}
	    	stack.push(i);
	    }
	    long ans = 0;
	    for(int i=0;i<n;i++) {
	    	ans=(ans+(long)(i-left[i])*(right[i]-i)*arr[i])%mod;
	    }
	    return (int) ans;
	    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值