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


    作者:Grey

    原文地址:子数组或者子矩阵的最大累加和问题

    子数组的最大累加和

    题目链接: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();
        }
    }
    

    更多

    算法和数据结构笔记

  • 相关阅读:
    vue2手写vuex
    200.岛屿数量(DFS M-岛屿系列)
    739.每日温度(栈M)
    150.逆波兰表达式求值(栈M)
    20.有效的括号(栈L)
    前端性能优化与SEO优化整理
    Typescript:类型断言
    如何在浏览器中快速调试Typescript
    Typescript:枚举
    Typescript:接口
  • 原文地址:https://www.cnblogs.com/greyzeng/p/16326526.html
Copyright © 2020-2023  润新知