力扣第1139题:最大的以1为边界的正方形(Java)

本文分享了一道动态规划题目——寻找矩阵中最大的1边界正方形的解题过程。作者首先分析了问题,提出使用三维数组表示状态,并通过状态转移方程求解。接着,通过遍历dp数组,不断更新最大边长,最终找到最大正方形。代码实现中,作者展示了如何判断并更新最大正方形的大小。虽然动态规划仍有一定挑战,但作者决心坚持每日练习以提升技能。
摘要由CSDN通过智能技术生成

一、前言

              今天依然是动态规划的题,老实说,今天的题目不是特别难,但是按照安排,还是照例写一份博客督促自己完成每日任务

二、题目描述

三、题目分析

        这个题目最初的时候,我打算从最中心处看起,逐渐向外扩散,但是后来发现我想的简单了,经过一番折腾,我尽可能的将思路清晰的讲出来。

        首先,因为是动态规划专题,所以重点在于状态转移方程的构建,那么就需要明确dp的含义,如果dp是一个二维数组dp[i][j],那么如何表示相邻正方形的关系呢?如果dp给定的是一个正方形,那么起码需要两个点,也就是四个xy坐标,那么至少需要一个四维数组并且关系式还难以给出。所以更好的方法是找出矩阵中一给定点那一行和那一列的连续1的数目,因为只有连续的一才可能满足条件。那么问题又来了,一行和一列的连续1的数目可能不同,怎么存在二维数组呢?那就开辟一个三维数组就是了,第三维的长度为2,分别表示 第i行和第j列。

        问题好像解决的差不多了,但是还有个更严重的,如果dp[i][j][0]指的是那一行连续1的个数,dp[i][j-1][0]指的也是那一行连续1的个数,就没有区别了!!所以我们将dp[i][j][0]的含义改为在(i,j)这个点左侧(包括自身)中连续1的数目,dp[i][j][1]的含义为该点上面连续1的个数。

        这样状态转移方程就容易得出了

    dp[i][j][0]=dp[i][j-1][0]+1;
    dp[i][j][1]=dp[i-1][j][1]+1;

        好的,当我们创建一个dp数组之后,通过状态转移方程的遍历,将所有dp的值都修改一番之后就到了下一步。

                                                (图非原创,侵删)

        下一步就是,先规定一个最大边的值为0。然后遍历dp数组,获取每个点的dp[i][j][0]和dp[i][j][1],取得其中的小值(因为如果该点左侧有五个连续1,上侧有三个连续1,那么正方形最大边长最多为3),记为currentside。每次遍历时都要进行一次判断,如果maxside大于currentside,那么进入到下个点的判断,否则,就要判断正方形的左边和上边是否满足条件(因为下边和右边已经满足),

        右下角为(i,j),边长为currentside,那么最左的那条边的最低点就是(i,j-currentside+1),只需要判断它的dp[i][j-currentside+1][1]是否大于等于3即可,同理,上面的那条边也可以这样计算。如果满足条件,那么更新maxside,否则就要将currentside减一,继续进入循环直到满足条件。

四、代码

 public int largest1BorderedSquare(int[][] grid) {
        int len_index=grid.length;//行数
        int len_column=grid[0].length;//列数
        int [][][]dp=new int [len_index+1][len_column+1][2];
        for(int i=1;i<=len_index;i++)//给dp重新赋值
            for(int j=1;j<=len_column;j++)
            {
                if(grid[i-1][j-1]==0)
                    continue;
                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<=len_index;i++)
            for(int j=1;j<=len_column;j++)
            {
                int currentside=Math.min(dp[i][j][0],dp[i][j][1]);
                if(maxside>=currentside)//满足条件则继续计算
                    continue;
                for(;currentside>maxside;currentside--)
                {
if (dp[i][j - currentside + 1][1] >= currentside && dp[i - currentside + 1][j][0] >= currentside) {
                    maxside = currentside;
                    break;
                }
                }
            }
        return maxside*maxside;
    }

 五、感言

        动态规划做了也有十多题了,但是大多还是不能完全独立做出来!郁闷郁闷!!!

        flag不倒,坚持每日一题!!

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少๑渊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值