zoukankan      html  css  js  c++  java
  • LeetCode 363:Max Sum of Rectangle No Larger Than K

    题目链接

    链接:https://leetcode.com/problems/max-sum-of-rectangle-no-larger-than-k/description/

    题解&代码

    1、暴力枚举所有的情况,时间复杂度O(n2*m2),实际耗时759 ms

    class Solution {
    public:
        int maxSumSubmatrix(vector<vector<int> >& matrix, int k) {
            int n=matrix.size(),m=matrix[0].size();
    
            vector<vector<int> > sumv(n+1,vector<int>(m+1,0));
            for(int i=1; i<=n; i++) {
                for(int j=1; j<=m; j++) {
                    sumv[i][j]=matrix[i-1][j-1]+sumv[i-1][j]+sumv[i][j-1]-sumv[i-1][j-1];
                }
            }
    
            int ans=-INF;
            for(int i1=1;i1<=n;i1++){
                for(int j1=1;j1<=m;j1++){
                    for(int i2=i1;i2<=n;i2++){
                        for(int j2=j1;j2<=m;j2++){
                            int val=sumv[i2][j2]-sumv[i1-1][j2]-sumv[i2][j1-1]+sumv[i1-1][j1-1];
                            if(val<=k){
                                ans=max(ans,val);
                            }
                        }
                    }
                }
            }
    
            return ans;
        }
    private:
        static const int INF=0x3f3f3f3f;
    };
    

    2、先通过枚举一维进行降维,然后再暴力枚举所有区间,时间复杂度O(m2*n2),实际耗时736ms。

    class Solution {
    public:
        int maxSumSubmatrix(vector<vector<int> >& matrix, int k) {
            int n=matrix.size(),m=matrix[0].size();
    
            vector<vector<int> > sumv(n+1,vector<int>(m+1,0));
            for(int i=1; i<=n; i++) {
                for(int j=1; j<=m; j++) {
                    sumv[i][j]=sumv[i][j-1]+matrix[i-1][j-1];
                }
            }
    
            int ans=-INF;
            vector<int> arr(n+1);
            for(int len=1; len<=m; len++) {
                for(int j=len; j<=m; j++) {
                    arr[0]=0;
                    for(int i=1; i<=n; i++) {
                        int val=sumv[i][j]-sumv[i][j-len];
                        arr[i]=val+arr[i-1];
    
                    }
                    for(int i=1;i<=n;i++){
                        for(int j=0;j<i;j++){
                            int x=arr[i]-arr[j];
                            if(x<=k) ans=max(ans,x);
                        }
                    }
    
                }
            }
            return ans;
        }
    private:
        static const int INF=0x3f3f3f3f;
    };
    

    3、 第2种方法基础上加一个剪枝,在枚举区间之前,先用dp(O(n))求出最大值区间和最小值区间,然后判断k是否在区间内,时间复杂度:‘玄学’,实际耗时19ms。

    class Solution {
    public:
        int maxSumSubmatrix(vector<vector<int> >& matrix, int k) {
            int n=matrix.size(),m=matrix[0].size();
    
            vector<vector<int> > sumv(n+1,vector<int>(m+1,0));
            for(int i=1; i<=n; i++) {
                for(int j=1; j<=m; j++) {
                    sumv[i][j]=sumv[i][j-1]+matrix[i-1][j-1];
                }
            }
    
            int ans=-inf;
            vector<int> arr(n+1);
            for(int len=1; len<=m; len++) {
                for(int j=len; j<=m; j++) {
                    arr[0]=0;
                    LL mi=inf,ma=-inf;
                    LL pre=inf,aft=-inf;
                    for(int i=1; i<=n; i++) {
                        int val=sumv[i][j]-sumv[i][j-len];
                        arr[i]=val+arr[i-1];
                        pre=min(pre+val,(LL)val);
                        aft=max(aft+val,(LL)val);
                        mi=min(mi,pre);
                        ma=max(ma,aft);
                    }
                    if(k<mi) continue;
                    else if(k==mi) {
                        ans=k;
                    } else if(k>=ma) {
                        ans=max((LL)ans,ma);
                    } else {
                        for(int i=1; i<=n; i++) {
                            for(int j=0; j<i; j++) {
                                int x=arr[i]-arr[j];
                                if(x<=k) ans=max(ans,x);
                            }
                        }
                        if(ans==k) return ans;
                    }
    
                }
            }
            return ans;
        }
    private:
        static const int inf=0x7fffffff;
        typedef long long LL;
    };
    

    4、正解:先降维,然后枚举区间终点,用set维护前缀和,用lower_bound去查区间起点,从而O(nlogn)的复杂度解决该问题的一维版本。加上降维的时间复杂度为O(m^2*nlogn)。实际耗时:259ms。

    class Solution {
    public:
        int maxSumSubmatrix(vector<vector<int> >& matrix, int k) {
            int n=matrix.size(),m=matrix[0].size();
    
            vector<vector<int> > sumv(n+1,vector<int>(m+1,0));
            for(int i=1; i<=n; i++) {
                for(int j=1; j<=m; j++) {
                    sumv[i][j]=sumv[i][j-1]+matrix[i-1][j-1];
                }
            }
    
            int ans=-INF;
            vector<int> pre(n+1),arr(n+1);
            set<pair<int,int> > myset;
            set<pair<int,int> >::iterator it;
            for(int len=1; len<=m; len++) {
                for(int j=len; j<=m; j++) {
                    pre[0]=0;
                    myset.clear();
                    for(int i=1; i<=n; i++) {
                        arr[i]=sumv[i][j]-sumv[i][j-len];
                        pre[i]=arr[i]+pre[i-1];
                        myset.insert(make_pair(pre[i],i));
                    }
                    for(int i=1;i<=n;i++){
                        if(arr[i]<=k) ans=max(ans,arr[i]);
                        int key=k-arr[i]+pre[i];
                        it=myset.lower_bound(make_pair(key,0x7fffffff));
                        if(it!=myset.begin()){
                            it--;
                            int tmp=it->first;
                            ans=max(ans,tmp-pre[i]+arr[i]);
                        }
                        myset.erase(make_pair(pre[i],i));
                    }
                }
            }
            return ans;
        }
    private:
        static const int INF=0x7fffffff;
    };
    

    5、正解优化版本(空间优化+常数优化)实际耗时:162ms。

    class Solution {
    public:
        int maxSumSubmatrix(vector<vector<int> >& matrix, int k) {
            int n=matrix.size(),m=matrix[0].size();
            int mi=min(n,m),ma=max(n,m);
            bool isColMax=m>n;
            int ans=-2147483648;
            for(int st=1; st<=mi; st++) {
                vector<int> arr(ma+1,0);
                for(int ed=st; ed<=mi; ed++) {
                    set<int> myset;
                    int cnt=0;
                    myset.insert(cnt);
                    for(int i=1; i<=ma; i++) {
                        arr[i]+=isColMax?matrix[ed-1][i-1]:matrix[i-1][ed-1];
                        cnt+=arr[i];
                        set<int>::iterator it=myset.lower_bound(cnt-k);
                        if(it!=myset.end()) ans=max(ans,cnt-*it);
                        myset.insert(cnt);
                    }
                }
            }
            return ans;
        }
    };
    

    6、方法5+方法3提到的dp剪枝:实际耗时:19ms。

    class Solution {
    public:
        int maxSumSubmatrix(vector<vector<int> >& matrix, int k) {
            int n=matrix.size(),m=matrix[0].size();
            int mi=min(n,m),ma=max(n,m);
            bool isColMax=m>n;
            int ans=-2147483648;
            for(int st=1; st<=mi; st++) {
                vector<int> arr(ma+1,0);
                for(int ed=st; ed<=mi; ed++) {
                    set<int> myset;
                    int cnt=0;
                    myset.insert(cnt);
                    for(int i=1; i<=ma; i++) {
                        arr[i]+=isColMax?matrix[ed-1][i-1]:matrix[i-1][ed-1];
                        cnt+=arr[i];
                        set<int>::iterator it=myset.lower_bound(cnt-k);
                        if(it!=myset.end()) ans=max(ans,cnt-*it);
                        myset.insert(cnt);
                    }
                }
            }
            return ans;
        }
    };
  • 相关阅读:
    为什么 execute(`echo 中文`) 输出中文源码?
    使用图片跨域方式获取图片数据 使用 jsonp 方式跨域获取数据
    js 中的 sleep 方法, 阻塞式
    大数据存储单位介绍(TB、PB、EB、ZB、YB有多大)
    在 chrome 开发工具中使用终端
    作为一个代码搬运工,如何应对突如其来的灵魂拷问『你今天做了什么』?
    JVM相关
    python和C++联合调试
    Google protobuf解析消息逻辑的版本问题
    卷积转换为矩阵运算中填充数的计算-GEMM
  • 原文地址:https://www.cnblogs.com/fenice/p/7278900.html
Copyright © 2011-2022 走看看