当前位置: 首页 > news >正文

丽水专业网站建设公司黄冈网站推广软件

丽水专业网站建设公司,黄冈网站推广软件,六安商城网站建设地址,相城网页设计摘要 1139. 最大的以 1 为边界的正方形 一、以1为边界的最大正方形 1.1 动态规划 第530题需要正方形所有网格中的数字都是1,只要搞懂动态规划的原理,代码就非常简洁。而这题只要正方形4条边的网格都是1即可,中间是什么数字不用管。 这题…

摘要

1139. 最大的以 1 为边界的正方形

一、以1为边界的最大正方形

1.1 动态规划

530题需要正方形所有网格中的数字都是1,只要搞懂动态规划的原理,代码就非常简洁。而这题只要正方形4条边的网格都是1即可,中间是什么数字不用管。

这题解题思路是这样的

  • 第一步先计算每个网格中横向和竖向连续1的个数。
  • 第二步遍历二维网格,以每一个格子为正方形的右下角,分别找出上边和左边连续1的个数,取最小值作为正方形的边长,然后判断正方形的左边和上边长度是否都大于等于正方形边长,如果都大于等于正方形边长就更新正方形的最大边长,否则缩小正方形的边长,继续判断……。

代码比较简单,我们定义一个三维数组,其中

  • dp[i][j][0]: (i,j)横向连续1的个数
  • dp[i][j][1]: (i,j)竖向连续1的个数

第一步: 我们计算的时候,如果当前位置是0就跳过,只有是1的时候才计算,分别统计左边和上边(也就是横向和竖向)连续1的个数。代码比较简单,我们来看下(这里为了减少一些边界条件的判断,把dp的宽和高都增加了1)。

int m = grid.length;
int n = grid[0].length;
//dp[i][j][0]: (i,j)横向连续1的个数
//dp[i][j][1]: (i,j)竖向连续1的个数
int[][][] dp = new int[m + 1][n+1][2];
for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {//如果当前位置是0,就跳过if (grid[i - 1][j - 1] == 0)continue;//如果是1,我们就计算横向和竖向连续1的个数dp[i][j][0] = dp[i][j - 1][0] + 1;dp[i][j][1] = dp[i - 1][j][1] + 1;}
}

第二步:找出正方形的最大边长

我们会以网格中的每一个位置为正方形的右下角,来找出正方形的边长。如下图所示,我们以橙色的位置1为正方形的右下角,分别沿着左边和上边找出他们连续1的个数,最小的作为正方形的边长。因为左边和上边连续1的个数我们在第一步的时候已经计算过,分别是dp[i][j][0]和dp[i][j][1],也就是正方形的边长我们暂时可以认为是

其实大家已经看到了这个边长就是正方形下边和右边的长度,但是正方形的上边和左边我们还没确定,我们继续确定正方形左边和上边的长度。会有两种情况

  • 一种如下图所示,就是正方形左边和上边的长度都大于curSide,我们可以认为以坐标(i,j)为右下角的正方形的最大长度就是curSide

另一种如下图所示,正方形上边的长度是1,小于curSide

 这种情况下是构不成正方形的,所以我们要缩小curSide的值,然后再继续判断

public int largest1BorderedSquare(int[][] grid) {int m = grid.length;int n = grid[0].length;//dp[i][j][0]: (i,j)横向连续1的个数//dp[i][j][1]: (i,j)竖向连续1的个数int[][][] dp = new int[m + 1][n + 1][2];for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {//如果当前位置是0,就跳过if (grid[i - 1][j - 1] == 0)continue;//如果是1,我们就计算横向和竖向连续1的个数dp[i][j][0] = dp[i][j - 1][0] + 1;dp[i][j][1] = dp[i - 1][j][1] + 1;}}int maxSide = 0;//记录正方形的最大长度for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {//沿着当前坐标往上和往左找出最短的距离,暂时看做是正方形的边长(正方形的具体边长//还要看上边和左边的长度,所以这里要判断一下)int curSide = Math.min(dp[i][j][0], dp[i][j][1]);//如果边长小于maxSide,即使找到了也不可能再比maxSide大,所以我们没必要再找,直接跳过,if (curSide <= maxSide)continue;//curSide可以认为是正方形下边和右边的长度,我们还需要根据正方形上边和左边的长度//来确认是否满足正方形的条件for (; curSide > maxSide; curSide--) {//判断正方形的左边和上边的长度是否大于curSide,如果不大于,我们就缩小正方形//的长度curSide,然后继续判断if (dp[i][j - curSide + 1][1] >= curSide && dp[i - curSide + 1][j][0] >= curSide) {maxSide = curSide;//更短的就没必要考虑了,这里直接中断break;}}}}//返回正方形的边长return maxSide * maxSide;
}

复杂度分析

  • 时间复杂度:O(m×n×min⁡(m,n)),其中 m 表示矩阵的行数,n 表示矩阵的列数。
  • 空间复杂度:O(m×n),其中 m 表示矩阵的行数,n 表示矩阵的列数。需要保存矩阵中每个位置的最长连续1的数目,需要的空间为 O(m×n)。

二、只是包含1的最大正方形

221. 最大正方形

在一个由 '0''1' 组成的二维矩阵内,找到只包含 '1' 的最大正方形,并返回其面积。

2.1 暴力求解

由于正方形的面积等于边长的平方,因此要找到最大正方形的面积,首先需要找到最大正方形的边长,然后计算最大边长的平方即可。

暴力法是最简单直观的做法,具体做法如下:

  • 遍历矩阵中的每个元素,每次遇到 1,则将该元素作为正方形的左上角;
  • 确定正方形的左上角后,根据左上角所在的行和列计算可能的最大正方形的边长(正方形的范围不能超出矩阵的行数和列数),在该边长范围内寻找只包含 1 的最大正方形;
  • 每次在下方新增一行以及在右方新增一列,判断新增的行和列是否满足所有元素都是 1。

package matrix;/*** @Classname 最大的正方形221* @Description TODO* @Date 2023/2/17 7:50* @Created by xjl*/
public class 最大的正方形221 {public int maximalSquare(char[][] matrix) {int maxSide=0;if (matrix==null||matrix.length==0||matrix[0].length==0){return maxSide;}int rows=matrix.length,colums=matrix[0].length;for (int i=0;i<rows;i++){for (int j=0;j<colums;j++){if (matrix[i][j]=='1'){// 遇到一个 1 作为正方形的左上角maxSide=Math.max(maxSide,1);// 计算可能的最大正方形边长 剩下的矩阵中的最大的正方形int currentMaxSide=Math.min(rows-i,colums-j);for (int k = 1; k < currentMaxSide; k++) {// 判断新增的一行一列是否均为 1boolean flag = true;// 判断是下一行和下一列是否为0 判断所有的对角线的元素 如果有存在的那就判断其他的四条边if (matrix[i + k][j + k] == '0') {break;}for (int m = 0; m < k; m++) {if (matrix[i + k][j + m] == '0' || matrix[i + m][j + k] == '0') {flag = false;break;}}if (flag) {maxSide = Math.max(maxSide, k + 1);} else {break;}}}}}int maxSquare = maxSide * maxSide;return maxSquare;}
}

2.2 动态规划求解

可以使用动态规划降低时间复杂度。我们用 dp(i,j) 表示以 (i,j) 为右下角,且只包含1的正方形的边长最大值。如果我们能计算出所有dp(i,j) 的值,那么其中的最大值即为矩阵中只包含1的正方形的边长最大值,其平方即为最大正方形的面积。

那么如何计算 dpdp 中的每个元素值呢?对于每个位置 (i,j)(i,j),检查在矩阵中该位置的值:

  • 如果该位置的值是 0,则 dp(i,j)=0,因为当前位置不可能在由 1 组成的正方形中;
  • 如果该位置的值是 1,则 dp(i,j)的值由其上方、左方和左上方的三个相邻位置的dp值决定。具体而言,当前位置的元素值等于三个相邻位置的元素中的最小值加1,状态转移方程如下:

dp(i,j)=min(dp(i-1,j),dp(i-1,j-1),dp(i,j-1))+1

此外,还需要考虑边界条件。如果 i 和 j 中至少有一个为0,则以位置 (i,j)为右下角的最大正方形的边长只能是 1,因此 dp(i,j)=1。

class Solution {public int maximalSquare(char[][] matrix) {int maxSide = 0;if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {return maxSide;}int rows = matrix.length, columns = matrix[0].length;int[][] dp = new int[rows][columns];for (int i = 0; i < rows; i++) {for (int j = 0; j < columns; j++) {if (matrix[i][j] == '1') {if (i == 0 || j == 0) {dp[i][j] = 1;} else {dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;}maxSide = Math.max(maxSide, dp[i][j]);}}}int maxSquare = maxSide * maxSide;return maxSquare;}
}

复杂度分析

  • 时间复杂度:O(mn),其m 和 n是矩阵的行数和列数。需要遍历原始矩阵中的每个元素计算dp的值。
  • 空间复杂度:O(mn),其中 m和n是矩阵的行数和列数。创建了一个和原始矩阵大小相同的矩阵 dp。由于状态转移方程中的 dp(i,j)由其上方、左方和左上方的三个相邻位置的 dp值决定,因此可以使用两个一维数组进行状态转移,空间复杂度优化至O(n)。

博文参考

《leetcode》

http://www.khdw.cn/news/22554.html

相关文章:

  • 个人主页设计模板图片seo网络推广什么意思
  • 公司免费网站建设seo技术助理
  • 政府门户网站建设方案网络推广网站电话
  • 企业建站系统cms长沙网站推广 下拉通推广
  • wordpress国外主题下载好的seo公司营销网
  • 传媒大学附近网站建设公司网站关键字优化
  • 速成网站-百度宣传广告要多少钱
  • 张家界网站定制营销方案的几个要素
  • 龙岗企业网站改版公司搜索引擎优化的基本内容
  • 网站被k后是怎样的网络推广方法
  • 域名做网站自己的电脑百度快照投诉中心人工电话
  • 一个网站如何做盈利网络推广外包怎么接单
  • dedecms 做门户网站电商平台推广方式有哪些
  • 品牌 网站建设怎么进行网络营销
  • 动易网站开发在线识别图片百度识图
  • 做淘宝客网站好搭建吗武汉百度开户代理
  • 今日新闻最新头条10条内容seo方法图片
  • 郑州市网站建设百度正版下载
  • 外贸工厂的网站建设青岛seo排名扣费
  • 如何在网站上做淘宝客推广西安整站优化
  • 河北建设厅网站查询百度seo排名软
  • 建个微网站多少钱百度网页入口
  • 静态网站中怎么做图片切换9个广州seo推广神技
  • 网站开发流程三部分福建省人民政府门户网站
  • 什么网站是html5做的网页制作培训网站
  • 教育网站建设需求分析报告网上怎么找客户资源
  • 西安培训网站建设网站推广教程
  • mac os 做网站网站维护费用一般多少钱
  • 做网商要创建网站吗b2b电子商务平台
  • 长春哪家做网站便宜太原网站推广排名