给定一个NxN矩阵mat和矩阵的阶数n,已知矩阵由正整数和负整数组成,请返回元素总和最大的子矩阵的元素之和。要求元素绝对值小于等于100000,尽量高效且矩阵阶数小于等于200。
测试样例:
[[1,2,-3],[3,4,-5],[-5,-6,-7]],3
返回:10
转换为单行求最大连续和问题。 class SubMatrix { private: int maxPartSum(vector<int>& nums) { int maxVal = nums[0],curVal = nums[0]; for (int i = 1; i < nums.size(); ++i) { if (curVal < 0) curVal = nums[i]; else curVal += nums[i]; maxVal = max({ maxVal, nums[i], curVal }); } return maxVal; } public: int sumOfSubMatrix(vector<vector<int>> mat, int n) { int maxSum = INT_MIN; for (int i = 0; i < n; ++i) { vector<int> dp(mat[i]); maxSum = max(maxSum, maxPartSum(dp)); for (int j = i + 1; j < n; ++j) { for (int k = 0; k < n; ++k) dp[k] += mat[j][k]; maxSum = max(maxSum, maxPartSum(dp)); } } return maxSum; } };
class SubMatrix: def sumOfSubMatrix(self, mat, n): sMax = mat[0][0] for i in xrange(n): # 上边界 A = [0] * n for j in xrange(i, n): # 下边界 for c in xrange(n): A[c] += mat[j][c] sMax = max(sMax, subMax(A, n)) # 最大连续子数组,降为O(N^3) return sMax def subMax(A, n): sMax, s = A[0], 0 for i in xrange(n): s += A[i] if s > sMax: sMax = s if s < 0: s = 0 return sMax
# -*- coding:utf-8 -*- def find_max(arr): if arr is None or len(arr) == 0: return 0 max_sum = cur_sum = float('-inf') for num in arr: if cur_sum <= 0: cur_sum = num else: cur_sum += num if cur_sum > max_sum: max_sum = cur_sum return max_sum """ 对每一行,与下面行累加,得到一个一维数组,用一维数组求连续子数组的最大和的方式求出最大和。O(N^2) """ def find_max_matrix(matrix, n): if n <= 0: return 0 max_sum = float('-inf') row = len(matrix) # 行数 for i in range(row): sum_arr = matrix[i] cur_sum = find_max(sum_arr) if cur_sum > max_sum: max_sum = cur_sum for j in range(i+1, row): sum_arr = [sum_arr[x]+matrix[j][x] for x in range(len(sum_arr))] cur_sum = find_max(sum_arr) if cur_sum > max_sum: max_sum = cur_sum return max_sum class SubMatrix: def sumOfSubMatrix(self, mat, n): return find_max_matrix(mat, n)
class SubMatrix { public: int max(int a,int b) { return a>b?a:b; } //求数组mat的最大累加和 int maxNumOfVector(vector<int> &mat,int n) { int res=numeric_limits<unsigned char>::min(); int curSum=0; for(int i=0;i<n;i++) { curSum+=mat[i]; res=max(res,curSum); if(curSum<0) curSum=0; } return res; } int sumOfSubMatrix(vector<vector<int> > mat, int n) { // write code here int res=numeric_limits<unsigned char>::min(); for(int i=0;i<n;i++) { vector<int> sum(n); for(int j=i;j<n;j++) { for(int k=0;k<n;k++) { sum[k]+=mat[j][k]; } res=max(res,maxNumOfVector(sum,n)); } } return res; } };
class SubMatrix { public: int check(vector<int> map, int max, int n){ vector<int> flag = map; for(int j = 1; j < n; j++) if(flag[j - 1] + map[j] > map[j]) flag[j] = flag[j - 1] + map[j]; for(int mm = 0; mm < n; mm++) if(max < flag[mm]) max = flag[mm]; return max; } int sumOfSubMatrix(vector<vector<int> > mat, int n) { long max = 0; for(int k = 0; k < n; k++){ vector<int> map(n, 0); map = mat[k]; max = check(map, max, n); for(int i = k + 1; i < n; i++){ for(int j = 0; j < n; j++) map[j] += mat[i][j]; max = check(map, max, n); } } return max; } };
/*思路: 1.求子矩阵的最大和,首先得判定所有可能的子矩阵(纵向选定) 2.纵向选定后,将这块子矩阵按行累加压缩成一维,然后处理简单的一维(横向选定) 3.过程中有最大值出现即时更新即可 */ public class SubMatrix { public int sumOfSubMatrix(int[][] mat, int n) { int maxSum = Integer.MIN_VALUE; int sum[] = new int[mat[0].length]; for(int i=0; i<mat.length; i++){//压缩的起点 for(int j=0; j<sum.length; j++) sum[j]=0;//每次更换起点sum就重置,感觉还可改进 for(int t=0; t<mat.length-i; t++){//步长,矩阵=起点+步长 for(int j=0; j<sum.length; j++) sum[j]+=mat[i+t][j];//求上述矩阵的压缩和 maxSum = Math.max(maxSum, getMaxSum(sum)); //压缩为一维求和,取最大值 } } return maxSum; } public int getMaxSum(int a[]){//常用,一维数组中连续子数组的最大和int maxSum = Integer.MIN_VALUE; int curSum = 0; for(int i=0; i<a.length; i++){ curSum += a[i]; maxSum = Math.max(maxSum, curSum); if(curSum<0) curSum=0; } return maxSum; } }
#include<iostream> #include<vector> using namespace std; class SubMatrix { public: int sumOfSubMatrix(vector<vector<int> > mat, int n) { // write code here //cout << maxSumMat(mat) << endl; return maxSumMat(mat); } int maxSumMat(vector<vector<int>> mat){ int n = mat.size(); int m = mat[0].size(); int res = 0; vector<int> b = mat[0]; for (int i = 0; i < mat.size(); ++i) { for (int k = 0; k < mat[0].size(); ++k) b[k] = 0; for (int j = i; j < mat.size(); j++) //枚举i - j行 { for (int k = 0; k < mat[0].size(); ++k){ b[k] += mat[j][k]; } int maxSubMat = maxSumArray(b); if (maxSubMat>res) res = maxSubMat; } } return res; } int maxSumArray( vector<int> data){ int cur= 0; int max = cur; int length = data.size(); for (int i = 0; i < length; i++){ if (cur>0){ cur+= data[i]; } else{ cur= data[i]; } if (cur > max) max = cur; } return max; } };
/*思路就是,(以第一行最为开始)先求第一行的最大和,然后将第二行数据加到第一行, 再求此时的最大值,然后再将下一行加上去,求最大值......最终得到第一列到最后一列的最大值; 还要计算第二行到最后一行的最大和,第三行到最后一行的最大和; */ class SubMatrix { public: int sumOfSubMatrix(vector<vector<int> > mat, int n) { // write code here if(n<=0) return 0; int maxVal = 0xffffffff; for(int i=0;i<n;i++) { vector<int> temp(mat[i]); maxVal=max(maxVal,helper(temp));//得到第一行的最大和 for(int j=i+1;j<n;j++)//循环下面的n-1行 { for(int k=0;k<n;k++)//将行的n个元素加到上一行,然后计算最大和 { temp[k]+=mat[j][k]; } maxVal=max(maxVal,helper(temp));//依次0~k行的最大和 } } return maxVal; } //求连续数组最大和,动态规划思想 int helper(vector<int>& vec)//求一维数组最大和 { int f=vec[0]; int result=f; for(int i=1;i<vec.size();i++) { f=max(f+vec[i],vec[i]); result=max(result,f); } return result; } };
//时间复杂度为O(n^3),空间复杂度为O(n) //把二维数组最大子矩阵和 转换成 一维数组的最大子数组: /*把二维数组M x N 每一行分别相加,就可以得出一个一维数组(长度为N), 这个一维数组的最大子数组和就是原矩阵中包含M行X列的一个最大子矩阵和, 这样只用枚举出原N x N 矩阵的所有 M x N的子矩阵的最大子矩阵和, 就可以得出最后结果*/ class SubMatrix { public: int sumOfSubMatrix(vector<vector<int> > mat, int n) { int maxVal = -(1<<31); for(int i = 0; i < n; i++){ vector<int> temp = mat[i]; maxVal = max(maxVal,helper(temp)); for(int j = i + 1; j < n; j++){ for(int k = 0; k < n; k++){ temp[k] += mat[j][k]; } maxVal = max(maxVal,helper(temp)); } } return maxVal; } //找出该数组的最大子数组和 int helper(vector<int> &a){ int temp = a[0]; int maxVal = temp; for(int i = 1; i < a.size(); i++){ if(temp < 0){ temp = a[i]; }else{ temp +=a[i]; } if(temp > maxVal){ maxVal = temp; } } return maxVal; } };
参考了 “忆水寒”的思路 class SubMatrix { public: int fundp(vector<int> mat) { int m=mat[0]; int res=m; for(int i=1;i<mat.size();i++)//动态规划求出每一行的最大和 { m=max(m+mat[i],mat[i]); res=max(res,m); } return res; } //思路就是从第一行开始,依次求出前1行最大和,前2行最大和。。。前n行最大和 //然后从第二行开始,依次求出第2行最大和,2-3行最大和,2-4行最大和。。。,2-n行最大和 //从第三行开始,3,3-4,3-5。。。3-n行最大和 //。。。 //n行 //比较求出最大和 int sumOfSubMatrix(vector<vector<int> > mat, int n) { int maxv=0; if(n<=0) return -1; for(int i=0;i<n;i++) { vector<int> temp(mat[i]); maxv=max(maxv,fundp(temp)); for(int j=i+1;j<n;j++) { for(int k=0;k<n;k++) { temp[k]+=mat[j][k]; } maxv=max(maxv,fundp(temp)); } } return maxv; } };
import java.util.*; public class SubMatrix { public int sumOfSubMatrix(int[][] mat, int n) { int max = Integer.MIN_VALUE; for(int i = 0; i < n; i++) { int[] temp = mat[i]; max = Math.max(max, helper(temp)); for(int j = i+1; j < n; j++) { for(int k = 0; k < n; k++) { temp[k] += mat[j][k]; } max = Math.max(max, helper(temp)); } } return max; } int helper(int[] a) { int temp = a[0]; int maxVal =temp; for(int i = 1; i < a.length; i++) { if(temp < 0) { temp = a[i]; }else { temp += a[i]; } maxVal = temp > maxVal? temp : maxVal; } return maxVal; } }
int sumOfSubMatrix(vector > mat, int n) { int max_sum=0; for(int i=0;i<n;i++) { vectorsum(n);//从第j=i行开始,每一列的数进行累加得到的和 for(int j=i;j<n;j++) { for(int k=0;k<n;k++) { sum[k]+=mat[j][k];//累计和 }//for max_sum=max(max_sum, helper(sum)); }//for }//for return max_sum; } int helper(vector nums)//一维数组最大值 { if(nums.size()==0) return 0; vectordp(nums.size());//动态规划标准解法 dp[0]=nums[0]; int max_val=nums[0]; for(int i=1;i<nums.size();i++) { dp[i]=max(nums[i], dp[i-1]+nums[i]); max_val=max(dp[i], max_val); } return max_val; }
};
class SubMatrix { public: int get(vector<vector<int>> &mat, vector<vector<int>> &sum, int x1, int y1, int x2, int y2) { return sum[x2][y2] - sum[x2][y1 - 1] - sum[x1 - 1][y2] + sum[x1 - 1][y1 - 1]; } int sumOfSubMatrix(vector<vector<int> > mat, int n) { int row = mat.size(), col = mat[0].size(); vector<vector<int>> sum(row + 10, vector<int>(col + 10, 0)); for (int i = 1; i <= row; ++ i) { for (int j = 1; j <= col; ++ j) { sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + mat[i - 1][j - 1]; } } int res = -0x3f3f3f3f; for (int x1 = 1; x1 <= row; ++ x1) { for (int y1 = 1; y1 <= col; ++ y1) { for (int x2 = x1; x2 <= row; ++ x2) { for (int y2 = y1; y2 <= col; ++ y2) { //cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << ' ' << get(mat, sum, x1, y1, x2, y2) << endl; res = max(res, get(mat, sum, x1, y1, x2, y2)); } } } } return res; } };
public class SubMatrix {
public int sumOfSubMatrix(int[][] mat, int n) {
// write code here
int rowCount = mat.length;
int columnCount = mat[0].length;
int[] partialSum = new int[columnCount];
int maxSum = Integer.MIN_VALUE;
for (int rowStart = 0; rowStart < rowCount; rowStart++) {
clearArray(partialSum);
for (int rowEnd = rowStart; rowEnd < rowCount; rowEnd++) {
for (int i = 0; i < columnCount; i++) {
partialSum[i] = partialSum[i] + mat[rowEnd][i];
}
int tempMaxSum = maxSubArray(partialSum);
maxSum = Math.max(maxSum,tempMaxSum);
}
}
return maxSum;
}
public int maxSubArray(int[] array) {
int maxSum = Integer.MIN_VALUE;
int runningSum = 0;
for (int i = 0; i < array.length; i++) {
runningSum = runningSum + array[i];
maxSum = Math.max(maxSum,runningSum);
if (runningSum < 0) {
runningSum = 0;
}
}
return maxSum;
}
public void clearArray(int[] array) {
for (int i = 0; i < array.length; i++) {
array[i] = 0;
}
}
}
//学高分大佬
class SubMatrix {
public:
int sumit(vector<int>& v, int n)
{
int tp=v[0];
int out=tp;
for(int i=1;i<n;i++)
{
tp=max(v[i],tp+v[i]);
out=max(out,tp);
}
return out;
}
int sumOfSubMatrix(vector<vector<int> > mat, int n) {
// write code here
int maxi=INT_MIN;
for(int i=0;i<n;i++)
{
vector<int> tp(mat[i]);
maxi=max(sumit(tp,n),maxi);
for(int j=i+1;j<n;j++)
{
for(int p=0;p<n;p++)
tp[p]+=mat[j][p];
maxi=max(sumit(tp,n),maxi);
}
}
return maxi;
}
};
//按行压缩成数组,转化成求子数组最大累加和的问题 import java.util.*; public class SubMatrix { public int sumOfSubMatrix(int[][] mat, int n) { // write code here if(mat == null || n == 0) return 0; int max = Integer.MIN_VALUE; int cur = 0; int[] s = null; for (int i = 0; i < n; i++){ s = new int[n]; for (int j = i; j < n; j++){ cur = 0; for (int k = 0; k < n; k++){ s[k] += mat[j][k]; cur += s[k]; if(cur > max) max = cur; if(cur < 0) cur = 0; } } } return max; } }
//时间复杂度为O(n^3) //详细原理参见:https://www.cnblogs.com/xiaoxi666/p/7341098.html class SubMatrix { public: int sumOfSubMatrix(vector<vector<int> > matrix, int n) { // write code here int max_sum=0; for(size_t i=0;i<matrix.size();++i) { vector<int> s(matrix[0].size()); for(size_t j=i;j<matrix[0].size();++j) { int sum_cur=0; for(size_t k=0;k<matrix[0].size();++k) { s[k]+=matrix[j][k]; sum_cur+=s[k]; sum_cur=sum_cur<0 ? 0 : sum_cur; max_sum=max(max_sum,sum_cur); } } } return max_sum; } };
class SubMatrix { public: int sumOfSubMatrix(vector<vector<int> > mat, int n) { // write code here int max = INT_MIN; for(int i=0; i<n; ++i){ vector<int> tmp(n, 0); for(int j=i; j<n; ++j){ for(int k=0; k<n; ++k) tmp[k]+=mat[j][k]; int temp = helper(tmp, n); if(temp>max) max=temp; } } return max; } private: int helper(vector<int>& vec, int n){ vector<int> dp; int max = INT_MIN; for(int i=0; i<n; ++i){ int tmp; if(i==0||dp[i-1]+vec[i]<vec[i]) tmp = vec[i]; else tmp = dp[i-1]+vec[i]; if(tmp>max) max=tmp; dp.push_back(tmp); } return max; } };
// vector中的最大值 int MaxOfVec(vector<int> v, int n) { int max = 0; int cur = 0; for (int i = 0; i < n; i++) { if (cur > 0) cur += v[i]; else cur = v[i]; max = max > cur ? max : cur; } return max; } int sumOfSubMatrix(vector<vector<int> > mat, int n) { // 遍历i-j行最大值 int res = 0; vector<int> cij = mat[0]; for (int i = 0; i < n; i++) { for (int a = 0; a < n; a++) cij[a] = 0; for (int j = i; j < n; j++) // i->j最大值 { for (int a = 0; a < n; a++) cij[a] += mat[j][a]; int m = MaxOfVec(cij, n); res = res > m ? res : m; } } // 防止全为负整数 if (res == 0) { res = mat[0][0]; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) res = res > mat[i][j] ? res : mat[i][j]; } return res; }
};