2018-09-27 23:33:49

问题描述:

问题求解:

方法一、DP(MLE)

动态规划的想法应该是比较容易想到的解法了,因为非常的直观,但是本题的数据规模还是比较大的,如果直接使用动态规划,即使不MLE,也是肯定会在大规模的数据量上TLE的。

  1. public int sumSubarrayMins(int[] A) {
  2. int res = 0;
  3. int mod = (int)Math.pow(10, 9) + 7;
  4. int[][] dp = new int[A.length][A.length];
  5. for (int i = 0; i < A.length; i++) dp[i][i] = A[i];
  6. for (int len = 2; len <= A.length; len++) {
  7. for (int i = 0; i <= A.length - len; i++) {
  8. int j = i + len - 1;
  9. dp[i][j] = Math.min(dp[i + 1][j], dp[i][j - 1]);
  10. }
  11. }
  12. for (int i = 0; i < A.length; i++) {
  13. for (int j = 0; j < A.length; j++) {
  14. res = (res + dp[i][j]) % mod;
  15. }
  16. }
  17. return res;
  18. }

方法二、

数据量已经基本表明时间复杂度在O(nlogn)左右比较好,那么直接使用dp肯定是不会通过所有的例子的。

本题还有另外一种思路:

res = sum(A[i] * f(i))
where f(i) is the number of subarrays,
in which A[i] is the minimum.

难点就在于求f(i),为了求f(i)需要求left[i]和right[i]。

left[i]:A[i]左边严格大于A[i]的个数

right[i]:A[i]右边大于等于A[i]的个数

f(i) = (left[i] + 1) * (right[i] + 1),其实就是一个排列组合,左边取一个可能,那么可以从右边取right[i] + 1种来进行组合。

这里需要特别注意的一点是:首先本问题是允许重复的子数组的,这里的重复是指数字上相等,但是是不允许完全一致的区间,因此左边必须是严格大于,否则会出现重复的情况。计算left,right数组可以使用Stack在O(n)时间复杂度完成求解,最后的res计算也是线性时间,因此总的时间复杂度为O(n)。

  1. public int sumSubarrayMins(int[] A) {
  2. int res = 0;
  3. int mod = (int)1e9 + 7;
  4. int[] left = new int[A.length];
  5. int[] right = new int[A.length];
  6. Stack<int[]> stack = new Stack<>();
  7. stack.push(new int[]{Integer.MIN_VALUE, -1});
  8. for (int i = 0; i < A.length; i++) {
  9. while (stack.peek()[0] > A[i])
  10. stack.pop();
  11. left[i] = i - stack.peek()[1];
  12. stack.push(new int[]{A[i], i});
  13. }
  14. stack.clear();
  15. stack.push(new int[]{Integer.MIN_VALUE, A.length});
  16. for (int i = A.length - 1; i >= 0; i--) {
  17. while (stack.peek()[0] >= A[i])
  18. stack.pop();
  19. right[i] = stack.peek()[1] - i;
  20. stack.push(new int[]{A[i], i});
  21. }
  22. for (int i = 0; i < A.length; i++) {
  23. res = (res + A[i] * left[i] * right[i]) % mod;
  24. }
  25. return res;
  26. }

子数组最小值的总和 Sum of Subarray Minimums的更多相关文章

  1. [LeetCode] 907. Sum of Subarray Minimums 子数组最小值之和

    Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarra ...

  2. [Swift]LeetCode907. 子数组的最小值之和 | Sum of Subarray Minimums

    Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarra ...

  3. LeetCode 643. 子数组最大平均数 I(Maximum Average Subarray I)

    643. 子数组最大平均数 I 643. Maximum Average Subarray I 题目描述 给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数. LeetCo ...

  4. 【LeetCode】643. 子数组最大平均数 I Maximum Average Subarray I (Python)

    作者: 负雪明烛 id: fuxuemingzhu 公众号:每日算法题 目录 题目描述 题目大意 解题方法 方法一:preSum 方法二:滑动窗口 刷题心得 日期 题目地址:https://leetc ...

  5. [Swift]LeetCode643. 子数组最大平均数 I | Maximum Average Subarray I

    Given an array consisting of n integers, find the contiguous subarray of given length k that has the ...

  6. [Swift]LeetCode930. 和相同的二元子数组 | Binary Subarrays With Sum

    In an array A of 0s and 1s, how many non-empty subarrays have sum S? Example 1: Input: A = [1,0,1,0, ...

  7. 907. Sum of Subarray Minimums

    Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarra ...

  8. 【leetcode】907. Sum of Subarray Minimums

    题目如下: 解题思路:我的想法对于数组中任意一个元素,找出其左右两边最近的小于自己的元素.例如[1,3,2,4,5,1],元素2左边比自己小的元素是1,那么大于自己的区间就是[3],右边的区间就是[4 ...

  9. leetcode907 Sum of Subarray Minimums

    思路: 对于每个数字A[i],使用单调栈找到A[i]作为最小值的所有区间数量,相乘并累加结果.时间复杂度O(n). 实现: class Solution { public: int sumSubarr ...

随机推荐

  1. svg动态添加小人

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  2. jQuery 表单内容的获取

    var formData = $('#myform').serialize()

  3. bzoj 2091 The Minima Game - 动态规划 - 博弈论

    题目传送门 需要验证权限的传送门 题目大意 Alice和Bob轮流取$n$个正整数,Alice先进行操作.每次每人可以取任意多的数,得分是这一次取的所有数中的最小值.Alice和Bob都足够聪明,他们 ...

  4. 尚硅谷面试第一季-14Redis持久化类型及其区别

    课堂重点: Redis提供了两种不同形式的持久化方案,分别是RDB和AOF. RDB使用Snapshot快照做全量的存储. RDB优缺点: AOF 以日志的方式记录每个写操作,只最佳,不该写文件.增量 ...

  5. TV Show Game 【2-SAT】

    问题 K: TV Show Game 时间限制: 1 Sec  内存限制: 512 MB  Special Judge 提交: 51  解决: 10 [提交] [状态] [命题人:admin] 题目描 ...

  6. codevs1017乘积最大

    codevs1017 乘积最大 题目描述 Description 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场 ...

  7. How to check if one path is a child of another path?

    How to check if one path is a child of another path? Unfortunately it's not as simple as StartsWith. ...

  8. 使用closest替换parent

    尽量不要使用parent去获取DOM元素,如下代码: var $activeRows = $this.parent().parent().children(".active"); ...

  9. map数据结构

    学习map的这种ES6新加的数据结构.在一些构建工具中是非常喜欢使用map这种数据结构来进行配置的,因为map是一种灵活,简单的适合一对一查找的数据结构.我们知道的数据结构,已经有了json和set. ...

  10. java web项目在linux部署、启动,查看系统配置常用的linux命令总结

    本文为博主原创,未经允许不得转载: 以下为在工作中常用的linux命令进行了总结,主要在项目安装及启动,及编辑部署文件时应用较多1.gz文件是一种压缩文件. 以·tar.gz为扩展名的是一种压缩文件, ...