题目
https://www.lintcode.com/problem/1489
java
给定一个大小
n∗m的矩阵arr,从arr中找出一个非空子矩阵,使位于这个子矩阵边界上的元素之和最大。输出该子矩阵的边界上的元素之和。
1≤n,m≤200
−10 ^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)
代码
java
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;
}
}