题目:
给定一个整数数组 arr,找到 min(b) 的总和,其中 b 的范围为 arr 的每个(连续)子数组。
由于答案可能很大,因此 返回答案模 10^9 + 7 。
示例:
示例 1:
输入:arr = [3,1,2,4]
输出:17
解释:
子数组为 [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。
示例 2:
输入:arr = [11,81,94,43,3]
输出:444
解题思路:
- 明确要求的是每个子数组都必须是连续的,然后找出子数组中的最小值。
- 那么从第一个元素开始,那么以该元素开头的连续的子数组就是
[arr[i]]、[arr[i], arr[i+1]]、[arr[i], arr[i+1], a[i+2]]、… 、[arr[i], arr[i+1], a[i+2], … ,a[i + arr.length-1 - i ]]
。 - 设置两个指针,p 是用来遍历整个数组, q是用来标记当前连续子数组的末尾元素位置。连续子数组就是从
p -> q
的所有元素。 - 标记当前元素为最小值
minValue
,然后q指针每往后移一位,则需要判断当前连续子数组的最小值,即minValue = Math.min(minValue, arr[q])
。然后将该值 加入res。 - 关键:每个元素作为连续子数组的首元素,然后从该元素往后遍历,每个元素作为连续子数组的尾元素。同时更新最小值。
代码:
/**
* @param {number[]} arr
* @return {number}
*/
var sumSubarrayMins = function(arr) {
let res = 0; // 结果
let p = 0; // 首元素指针
while (p < arr.length){
let q = p; // 尾元素指针
let minV = arr[p] // 保存连续子元素最小值
while(q < arr.length){
minV = Math.min(minV, arr[q]) // 更新最小值
res += minV; // 将最小值加一起
q++;
}
p++;
}
return res % 1000000007; // 结果对 10^9 + 7取余
};