LeetCode 363 矩形区域不超过 K 的最大数值和

给定一个矩阵,要求找出矩阵内部不大于k的最大矩阵和。如果枚举每个矩阵,并计算其和,必定会超时。我最开始想的是暴力+动态规划,用dp[i][j]表示以(0,0)为左上角,以(i,j)为右下角的矩阵的和,这样子省去了重复计算矩阵和的时间,虽然能通过,但是时间复杂度还是到了O(m²n²),不是很好,优点就是简单易懂。后来,看了题解中的一些方法进行改进,因为题目中提到了行数可能远大于列数,我们固定列数的左右边界,之后求在边界中每行的和,然后再求出符合要求的矩阵和,时间复杂度是在理想的情况下可达到O(m²n),速度也有很大地提升。

暴力+动态规划

class Solution {
public:
    int dp[2005][2005];
    int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
        int n=matrix.size(),m;
        if(n) m=matrix[0].size();
        if(n==0) return 0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+matrix[i-1][j-1];
        int ans=-0x3f3f3f3f,t;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                for(int r=0;r<=i;r++)
                    for(int c=0;c<=j;c++)
                    if(r!=i&&c!=j)
                    {
                        t=dp[i][j]-dp[i][c]-dp[r][j]+dp[r][c];
                        if(t>ans&&t<=k) ans=t;
                    }
            }
    return ans;
    }
};

滚动数组+子区间和(改进版)

class Solution {
public:
    int dpmax(int *sum,int n,int k)
    {
        int ans=-0x3f3f3f3f,now=0;
        for(int i=0;i<n;i++)
        {
            if(now>0) now+=sum[i];
            else now=sum[i];
            if(now>ans) ans=now;  
        }
        if(ans<=k) return ans;
        ans=-0x3f3f3f3f;
        for(int i=0;i<n;i++)
        {
            now=0;
            for(int j=i;j<n;j++)
            {
                now+=sum[j];
                if(now<=k&&now>ans) ans=now;
                if(ans==k) return ans;
            }
        }
        return ans;
    }
    int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
        int n=matrix.size(),m;
        if(n) m=matrix[0].size();
        if(n==0) return 0;
        int *sum=new int[n+1];
        int ans=-0x3f3f3f3f;
        for(int i=0;i<m;i++)
            for(int j=i;j<m;j++)
            {
                for(int x=0;x<n;x++) sum[x]=0;
                for(int r=0;r<n;r++)
                    for(int c=i;c<=j;c++)
                        sum[r]+=matrix[r][c];
                ans=max(ans,dpmax(sum,n,k));
            }
        
        return ans;
    }
};
posted @ 2020-05-07 19:13  South1999  阅读(130)  评论(0编辑  收藏  举报