zoukankan      html  css  js  c++  java
  • 【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)
  • 相关阅读:
    前端开发聚合
    6. webRTC
    14.移动端图片浏览组件 react-wx-images-viewer
    windows下怎样使用md命令一次建立多级子目录
    mysql打印输出转csv格式
    Java Stream简介, 流的基本概念
    Linux使用Shell脚本实现ftp的自动上传下载
    在Linux中设置UMASK值
    SFTP+OpenSSH+ChrootDirectory设置
    导出php5.4支持的数组格式,即以[]为标识符而不是以array()标识
  • 原文地址:https://www.cnblogs.com/flix/p/13525561.html
Copyright © 2011-2022 走看看