给定一个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;
}
};