这道题我的想法就是使用暴力搜索,维护两个节点,第一个节点是矩阵的左上角,第二个节点是矩阵的右下角。然后在围起来的矩阵里面去计算面积。
假设矩阵的行为M,矩阵的列为N,那么上述算法的事件复杂度为O(MN*MN*MN)。因此肯定是不可行的。
于是只能采用用空间换取时间的方法,对于每个节点,将(0,0)看做矩阵的左上角,将当前节点看成矩阵的右下角,记录下当前节点对应的行和宽。
但是很不幸,代码TLE,原因在于,在计算面积时还是要有个for循环。
于是又更新了一般,这一版里面维护了以当前节点为右下角,以(0,0)为左上角的矩阵的面积。OK,通过!
代码1:
public class Solution {
class Node{
int totalRow;
int totalCol;
Node(int rowVal,int colVal){
totalRow = rowVal;
totalCol = colVal;
}
}
public int maxSumSubmatrix(int[][] matrix, int k) {
int row = matrix.length;
int col = matrix[0].length;
Node[][] totalMatrix = new Node[row][col];
initTotalMatrix(matrix,totalMatrix);
int max = Integer.MIN_VALUE;
for(int rowUp = 0;rowUp<row;rowUp++){
for(int colUp = 0;colUp<col;colUp++){
for(int rowDown = rowUp;rowDown<row;rowDown++){
for(int colDown = colUp;colDown<col;colDown++){
int res = getArea(matrix,totalMatrix,rowUp,colUp,rowDown,colDown);
if(res <= k){
if(res == k)
return res;
if(res > max)
max = res;
}
}
}
}
}
return max;
}
private int getArea(int[][] matrix,Node[][] totalMatrix,int upRow,int upCol,int downRow,int downCol){
int col = downCol-upCol;
int row = downRow-upRow;
int res = 0;
if(col < row){
for(int i = upCol;i<=downCol;i++){
res += totalMatrix[downRow][i].totalCol - totalMatrix[upRow][i].totalCol + matrix[upRow][i];
}
}else{
for(int i = upRow;i<=downRow;i++){
res += totalMatrix[i][downCol].totalRow - totalMatrix[i][upCol].totalRow + matrix[i][upCol];
}
}
return res;
}
private void initTotalMatrix(int[][] matrix,Node[][] totalMatrix){
int row = matrix.length;
int col = matrix[0].length;
Node tmp;
for(int i = 0;i<row;i++){
for(int j = 0;j<col;j++){
tmp = new Node(matrix[i][j],matrix[i][j]);
totalMatrix[i][j] = tmp;
if(i > 0){
Node prevRowNode = totalMatrix[i-1][j];
tmp.totalCol += prevRowNode.totalCol;
}
if(j > 0){
Node prevColNode = totalMatrix[i][j-1];
tmp.totalRow += prevColNode.totalRow;
}
}
}
}
}
更新后:
public class Solution {
class AreaNode{
int area;
AreaNode(int area){
this.area = area;
}
}
class TotalNode{
int totalRow;
int totalCol;
TotalNode(int row,int col){
totalRow = row;
totalCol = col;
}
}
public int maxSumSubmatrix(int[][] matrix, int k) {
int row = matrix.length;
int col = matrix[0].length;
AreaNode[][] areaMatrix = new AreaNode[row][col];//保存面积信息
TotalNode[][] totalMatrix = new TotalNode[row][col];//保存行列信息
initareaMatrix(matrix,areaMatrix,totalMatrix);
int max = Integer.MIN_VALUE;
for(int rowUp = 0;rowUp<row;rowUp++){
for(int colUp = 0;colUp<col;colUp++){
for(int rowDown = rowUp;rowDown<row;rowDown++){
for(int colDown = colUp;colDown<col;colDown++){
int res = getArea(areaMatrix,totalMatrix,rowUp,colUp,rowDown,colDown) + matrix[rowUp][colUp];
if(res <= k){
if(res == k)
return res;
if(res > max)
max = res;
}
}
}
}
}
return max;
}
private int getArea(AreaNode[][] areaMatrix,TotalNode[][] totalMatrix,int upRow,int upCol,int downRow,int downCol){
return areaMatrix[downRow][downCol].area - areaMatrix[upRow][downCol].area - areaMatrix[downRow][upCol].area
+ areaMatrix[upRow][upCol].area + totalMatrix[upRow][downCol].totalRow - totalMatrix[upRow][upCol].totalRow
+totalMatrix[downRow][upCol].totalCol - totalMatrix[upRow][upCol].totalCol;
}
private void initareaMatrix(int[][] matrix,AreaNode[][] areaMatrix,TotalNode[][] totalMatrix){
int row = matrix.length;
int col = matrix[0].length;
for(int i = 0;i<row;i++){
for(int j = 0;j<col;j++){
int res = 0;
int totalRow = matrix[i][j];
int totalCol = matrix[i][j];
if(i > 0){
res += areaMatrix[i-1][j].area;
totalCol += totalMatrix[i-1][j].totalCol;
}
if(j > 0){
res += areaMatrix[i][j-1].area;
totalRow += totalMatrix[i][j-1].totalRow;
}
if(i > 0&&j > 0){
res -= areaMatrix[i-1][j-1].area;
}
res += matrix[i][j];
areaMatrix[i][j] = new AreaNode(res);
totalMatrix[i][j] = new TotalNode(totalRow,totalCol);
}
}
}
}