• 【LeetCode-动态规划】最大的以 1 为边界的正方形


    题目描述

    给你一个由若干 0 和 1 组成的二维网格 grid,请你找出边界全部由 1 组成的最大 正方形 子网格,并返回该子网格中的元素数量。如果不存在,则返回 0。
    示例:

    输入:grid = [[1,1,1],[1,0,1],[1,1,1]]
    输出:9
    
    输入:grid = [[1,1,0,0]]
    输出:1
    

    示例:

    • 1 <= grid.length <= 100
    • 1 <= grid[0].length <= 100
    • grid[i][j] 为 0 或 1

    题目链接: https://leetcode-cn.com/problems/largest-1-bordered-square/

    思路

    这题和统计全 1 子矩形有点类似,使用动态规划来做。

    • 状态定义:使用两个状态:left[i][j] 表示位置 (i, j) 左边 1 的个数(包括位置 (i, j)),up[i][j] 表示位置 (i, j) 上边 1 的个数(包括位置 (i, j));
    • 状态转移:如果 grid[i][j]==1,left[i][j] = left[i][j-1] + 1,up[i][j] = up[i-1][j] + 1;
    • 边界条件(grid[i][j]==1 的情况下):
      • i==0 && j==0:left[i][j] = up[i][j] = 1;
      • i==0 && j!=0:left[i][j] = left[i][j-1] + 1; up[i][j] = 1;
      • i!=0 && j==0:left[i][j] = 1; up[i][j] = up[i-1][j] + 1;

    对于每一个位置(i, j),left[i][j] 表示该位置左边有多少 1,up[i][j] 表示该位置上边有多少 1,则以位置 (i, j) 为右下角的正方形的最大边长 len = min(left[i][j], up[i][j]),我们需要判断 left[i-k+1][j](右上角) 和 up[i][j-k+1](左下角)1 的个数是不是大于等于 k,k ∈ [1, len],选择最大的 k 作为以位置 (i, j) 为右下角的正方形的边长。在遍历的过程中记录最大边长。代码如下:

    class Solution {
    public:
        int largest1BorderedSquare(vector<vector<int>>& grid) {
            if(grid.empty()) return 0;
    
            int m = grid.size();
            int n = grid[0].size();
            vector<vector<int>> left(m, vector<int>(n, 0));
            vector<vector<int>> up(m, vector<int>(n, 0));
            for(int i=0; i<m; i++){
                for(int j=0; j<n; j++){
                    if(grid[i][j]==1){
                        if(i==0 && j==0){
                            left[i][j] = 1;
                            up[i][j] = 1;
                        }else if(i==0){
                            left[i][j] = left[i][j-1] + 1;
                            up[i][j] = 1;
                        }else if(j==0){
                            left[i][j] = 1;
                            up[i][j] = up[i-1][j] + 1;
                        }else{
                            left[i][j] = left[i][j-1] + 1;
                            up[i][j] = up[i-1][j] + 1;
                        }
                    }
                }
            }
    
            int ans = 0;
            for(int i=0; i<m; i++){
                for(int j=0; j<n; j++){
                    int len = min(left[i][j], up[i][j]);
                    for(int k=len; k>0; k--){
                        if(left[i-k+1][j]>=k && up[i][j-k+1]>=k){
                            ans = max(ans, k);
                            break;
                        }
                    }
                }
            }
            return ans*ans;
        }
    };
    
    • 时间复杂度:O(mn)
    • 空间复杂度:O(mn)
  • 相关阅读:
    Struts访问servletAPI方式
    Struts结果跳转方式(四种result配置)
    struts与ognl结合【重要】
    Yii --Command 任务处理
    安卓 短信去重(看好了,是短信去重,不是联系人去重)
    快速排序算法之我见(附上C代码)
    Ext JS4百强应用:设置textfield的悬浮提示信息 --第8强
    窗体添加阴影效果如此简单
    使用apache daemon让java程序在unix系统上以服务方式运行
    控件布局通用解决方案
  • 原文地址:https://www.cnblogs.com/flix/p/13525561.html
Copyright © 2020-2023  润新知