Loading

子数组或者子矩阵的最大累加和问题

子数组或者子矩阵的最大累加和问题

作者:Grey

原文地址:

博客园:子数组或者子矩阵的最大累加和问题

CSDN:子数组或者子矩阵的最大累加和问题

子数组的最大累加和

题目链接:LeetCode 53. 最大子数组的和

主要思路:

设置dp数组,长度和原始数组一样,dp[i]表示必须以i位置结尾的子数组,最大累加和是多少,设置一个全局max,获取dp数组的最大值,即为原始数组的最大子数组的和。

显然有:

// 必须以0位置结尾的子数组,最大累加和显然就是arr[0]
dp[0] = arr[0]

考虑普遍位置

// dp[i-1]表示:必须以i-1位置的数结尾的最大子数组累加和是多少
// dp[i]表示:必须以i位置的数结尾的最大子数组累加和是多少
// 假设dp[i-1]>0,则dp[i-1]的和可以给予dp[i]帮助
// 否则,dp[i-1]不能给予dp[i]帮助,此时,dp[i] = arr[i]
dp[i] = arr[i] + (dp[i-1]>0?dp[i-1]:0);

完整代码如下

 public static int maxSubArray(int[] arr) {
  // dp[i]表示:子数组必须以i结尾的情况下,最大累加和是多少
  int[] dp = new int[arr.length];
  int max = arr[0];
  dp[0] = arr[0];
  for (int i = 1; i < arr.length;i++) {
   dp[i] = arr[i] + (Math.max(dp[i - 1], 0)); 
   max = Math.max(max,dp[i]);
  }
  return max;
 }

通过如上算法,可以看到dp[i]只依赖dp[i-1]位置的值,所以,dp数组可以简化成两个变量,依次传递下去,优化后的完整代码如下:

 public static int maxSubArray(int[] arr) {
  int pre = arr[0];
  int max = pre;
  for (int i = 1; i < arr.length; i++) {
   int cur = arr[i] + (Math.max(pre, 0));
   max = Math.max(max, cur);
   pre = cur;
  }
  return max;
 }

子矩阵的最大累加和问题

题目链接:子矩阵的最大累加和问题

这个题目可以借鉴子数组的最大累加和问题的算法,假设我们的二位矩阵是:

[a,b,c,d,e]
[f,g,h,i,j]
[k,l,m,n,o]
[p,q,r,s,t]
[u,v,w,x,y]

假设客观上,最大子矩阵的和是这些数的和

[k,l,m]
[p,q,r]
[u,v,w]

即第3行,第4行,第5行的前面三个数组成的矩阵,其实,它就是,第3行到第5行的对应位置数字之和组成的一维数组的最大子数组的累加和

[k+p+u,l+q+v,m+r+w,n+s+x,o+t+y]

这样一来,我们可以把问题转换一下,必须以i行为底的子矩阵的最大累加和是多少,如果我们求得了每一行的这个指标,那么最大值就是本题的答案。比如:必须以第2行为底的子矩阵的最大累加和,我们可以这样算:

第0行~第2行的对应位置数据累加后的一维数组

[a+f+k,b+g+l,c+h+m,d+i+n,e+j+o]

子数组最大累加和为max1,

第1行~第2行的对应位置数据累加和后的一维数组

[f+k,g+l,h+m,i+n,j+o]

子数组最大累加和为max2,

第2行单独一行的一维数组是

[k,l,m,n,o]

子数组最大累加和为max3

那么必须以第2行为底的子矩阵的最大累加和就是max1,max2,max3中的最大值。

对每一行都求这个指标,得到每一行为底的最大子矩阵累加和,得到全局最大的那个就是答案。

完整代码如下:

import java.util.Scanner;

public class Main {
    public static int maxSum(int[][] matrix, int n, int m) {
        int[] t;
        int max = maxSubArray(matrix[0]);
        for (int i = 0; i < n; i++) {
            max = Math.max(maxSubArray(matrix[i]), max);
            t = matrix[i];
            for (int k = i + 1; k < n; k++) {
                for (int j = 0; j < m; j++) {
                    t[j] += matrix[k][j];
                }
                max = Math.max(max, maxSubArray(t));
            }
        }
        return max;
    }

    public static int maxSubArray(int[] arr) {
        int pre = arr[0];
        int max = pre;
        for (int i = 1; i < arr.length; i++) {
            int cur = arr[i] + (Math.max(pre, 0));
            max = Math.max(max, cur);
            pre = cur;
        }
        return max;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        int[][] matrix = new int[n][m];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                matrix[i][j] = in.nextInt();
            }
        }
        System.out.println(maxSum(matrix, n, m));
        in.close();
    }
}

更多

算法和数据结构笔记

posted @ 2022-05-30 13:51  Grey Zeng  阅读(109)  评论(0编辑  收藏  举报