lintcode 1489 · 最大矩阵边界和 【前缀和数组 中等 vip】

题目

https://www.lintcode.com/problem/1489

给定一个大小
n∗m的矩阵arr,从arr中找出一个非空子矩阵,使位于这个子矩阵边界上的元素之和最大。输出该子矩阵的边界上的元素之和。

1≤n,m≤20010 ^3 ≤arr[i][j]10 ^3
 
样例
样例1

输入: arr=[[-1,-3,2],[2,3,4],[-3,7,2]]
输出: 16
样例说明: 子矩阵[[3,4],[7,2]]的轮廓元素之和最大.
样例2

-1
最大的。
样例3

输入: arr=[1,1,1],[1,2,1],[1,1,1]
输出: 8
样例说明:选取整个矩阵,轮廓和为8,最大。

思路

	 prefixSum + enumeration
    for each row and column, set up the prefixSum Array:

    rowPrefixSumArray[n][m+1] : for each row, record the prefix sumarray of [0..n-1][0..m]
    colPrefixSumArray[m][n+1] : for each column, record the prefix sum array of [0..m-1][0..n]

    for (i1 = 0..n-1, j1=0..m-1)
        for (i2 = i1..n-1, j2=j1..m-1)
            maxSum = max(maxSum, calcBoundarySum(i1, j1, i2, j2))
    return maxSum

    T=O(n * m)^2), S=O(n * m)

代码

public class Solution {
    /**
     * @param arr: the matrix
     * @return: Return the largest sum of the matrix boundary elements
     */
    public int solve(int[][] arr) {
             /*
        prefixSum + enumeration
        for each row and column, set up the prefixSum Array:

        rowPrefixSumArray[n][m+1] : for each row, record the prefix sumarray of [0..n-1][0..m]
        colPrefixSumArray[m][n+1] : for each column, record the prefix sum array of [0..m-1][0..n]

        for (i1 = 0..n-1, j1=0..m-1)
            for (i2 = i1..n-1, j2=j1..m-1)
                maxSum = max(maxSum, calcBoundarySum(i1, j1, i2, j2))
        return maxSum

        T=O(n * m)^2), S=O(n * m)
        */
        if (arr == null || arr.length == 0 || arr[0] == null || arr[0].length == 0)
            return 0;
        int n = arr.length, m = arr[0].length;
        int[][] rowPreSum = createRPS(arr, n, m);  //每一行的前缀和
        int[][] colPreSum = createCPS(arr, n, m);  //没一列的前缀和

        int maxSum = Integer.MIN_VALUE;
        for (int i1 = 0; i1 < n; i1++) {
            for (int j1 = 0; j1 < m; j1++) {
                for (int i2 = i1; i2 < n; i2++) {
                    for (int j2 = j1; j2 < m; j2++) {
                        int curMatrixSum = f(arr, rowPreSum, colPreSum, i1, j1, i2, j2);
                        maxSum = Math.max(maxSum, curMatrixSum);
                    }
                }
            }
        }
        return maxSum;
    }

    /*
     -1 -3 2
     2 3 4
     -3 7 2

     rowPreSum:
     0 -1 -4 -2
     0 2 5 9
     0 -3 4 6

     colPreSum:
     0 0   0
     -1 -3 2
     1  0. 6
     -2 7. 8
     */
    public static int[][] createRPS(int[][] arr, int n, int m) {
        int[][] sum = new int[n][m + 1];
        for (int row = 0; row < n; row++) {
            sum[row][0] = 0; //可以不设置,默认就是0
            for (int col = 1; col <= m; col++) {
                sum[row][col] = sum[row][col - 1] + arr[row][col - 1];
            }
        }

        return sum;
    }

    public static int[][] createCPS(int[][] arr, int n, int m) {
        int[][] sum = new int[n + 1][m];
        for (int col = 0; col < m; col++) {
            sum[0][col] = 0;//可以不设置,默认值是0
            for (int row = 1; row <= n; row++) {
                sum[row][col] = sum[row - 1][col] + arr[row - 1][col];
            }
        }

        return sum;
    }
        /*
                  j1      j2
        i1 :      X        X

        i2 :      X        X
        */

    public static int f(int[][] arr, int[][] rowSum, int[][] colSum, int i1, int j1, int i2, int j2) {
        int sum = 0;
        sum += rowSum[i1][j2 + 1] - rowSum[i1][j1];  //row: i1 (j1..j2)
        if (i1 == i2) return sum;

        //row: i2 (j1..j2)
        sum += rowSum[i2][j2 + 1] - rowSum[i2][j1];

        // col j1, row: i1+1, i2-1: colSum[i2-1+1][j1]  -  colSum[i1+1][j1] (i1< i1+1 <= i2-1 < i2)
        // col j2, row: i1+1, i2-1: colSum[i2-1+1][j2]  -  colSum[i1+1][j2] (i1< i1+1 <= i2-1 < i2)

        if (i1 < i2-1) {
            sum += colSum[i2][j1] - colSum[i1 + 1][j1];
            sum += colSum[i2][j2] - colSum[i1 + 1][j2];
        }
        return sum;
    }
}

你可能感兴趣的:(矩阵,算法)