【算法训练-动态规划 五】【二维DP问题】最大正方形

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【动态规划】,使用【数组】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为:目标公司+最近一年+出现频率排序,由高到低的去牛客TOP101去找,只有两个地方都出现过才做这道题(CodeTop本身汇聚了LeetCode的来源),确保刷的题都是高频要面试考的题。
在这里插入图片描述

明确目标题后,附上题目链接,后期可以依据解题思路反复快速练习,题目按照题干的基本数据结构分类,且每个分类的第一篇必定是对基础数据结构的介绍

最大正方形【MID】

来解决一道最大正方形的题目

题干

在这里插入图片描述

解题思路

原题解出处按照动态规划的标准解题讨论来进行解题,理解 min(上, 左, 左上) + 1,如题,在其他动态规划方法的题解中,大都会涉及到下列形式的代码:

// 伪代码
if (matrix(i , j ) == '1') {
    dp(i, j) = min(dp(i - 1, j), dp(i, j - 1), dp(i - 1, j - 1)) + 1;
}

其中,dp(i, j) 是以 matrix(i , j )右下角 的正方形的最大边长

若某格子值为 1,则以此为右下角的正方形的、最大边长为:上面的正方形、左面的正方形或左上的正方形中,最小的那个,再加上此格

先来阐述简单共识

  • 若形成正方形(非单 1),以当前为右下角的视角看,则需要:当前格、上、左、左上都是 1
  • 可以换个角度:当前格、上、左、左上都不能受 0 的限制,才能成为正方形

在这里插入图片描述
上面详解了 三者取最小 的含义:

  • 图 1:受限于左上的 0
  • 图 2:受限于上边的 0
  • 图 3:受限于左边的 0

数字表示:以此为正方形右下角的最大边长;黄色表示:格子 ? 作为右下角的正方形区域。就像 木桶的短板理论 那样——附近的最小边长,才与 ? 的最长边长有关。 此时已可得到递推公式

// 伪代码
if (grid[i][j] == '1') {
    dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1;
}

1 定义状态(定义子问题)

dp 具体定义:dp[i ][j ] 表示 「以第 i 行、第 j 列为右下角的正方形的最大边长」

为何不是 dp[i][j],回到图解中,任何一个正方形,我们都「依赖」当前格 左、上、左上三个方格的情况,但第一行的上层已经没有格子,第一列左边已经没有格子,需要做特殊 if 判断来处理,为了代码简洁,我们 假设补充 了多一行全 ‘0’、多一列全 ‘0’

2 状态转移方程(描述子问题之间的联系)

取自己左上、上方、左边最小值再加上自身

// 伪代码
if (grid[i][j] == '1') {
    dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]) + 1;
}

3 初始化状态

初始值就是将第一列 dp[row][0] 、第一行 dp[0][col] 都赋为 0,相当于已经计算了所有的第一行、第一列的 dp 值
在这里插入图片描述

4 求解方向

这里采用自底向上,从最小的状态开始求解

5 找到最终解

题目要求面积。根据 「面积 = 边长 x 边长」可知,我们只需求出 最大边长 即可,定义 maxSide 表示最长边长,每次得出一个 dp,就 maxSide = max(maxSide, dp); 最终返回 return maxSide * maxSide;

代码实现

给出代码实现基本档案

基本数据结构数组
辅助数据结构
算法动态规划
技巧

其中数据结构、算法和技巧分别来自:

  • 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
  • 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
  • 技巧:双指针、滑动窗口、中心扩散

当然包括但不限于以上

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param nums int整型一维数组
     * @return int整型一维数组
     */
    public int maximalSquare(char[][] matrix) {

        // 1 入参校验
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return 0;
        }
        // 2 定义最长边,以及获取边长
        int maxSide = 0;
        int row = matrix.length;
        int col = matrix[0].length;

        // 3 定义dp数组,dp[i][j]表示以i、j为坐标的元素作为右下角的最大正方形边长,默认初始化了两列0
        int[][] dp = new int[row + 1][col + 1];

        // 4 编写状态转移方程
        for (int i = 1; i <= row; i++) {
            for (int j = 1; j <= col; j++) {
                if (matrix[i - 1][j - 1] == '1') {
                    dp[i][j] = Math.min(dp[i - 1][j], Math.min(dp[i][j - 1], dp[i - 1][j - 1])) + 1;
                    maxSide = Math.max(maxSide, dp[i][j]);
                }
            }
        }
        return maxSide * maxSide;
    }
}

考虑到每个方格都需要参与计算,双重循环要从索引1开始(否则dp[0][0]无法进行状态转移,会数组越界),这样为了第0行第0列可以参与计算,就给dp数组补了0,也就是base case,补0后dp的第1行和第1列对应的判断元素其实是matrix的第0行和第0列,所以这里的if条件是:matrix[i - 1][j - 1] == '1'

复杂度分析

时间复杂度:O(N^2),这里 N 是数组的长度,我们写了两个 for 循环,每个 for 循环的时间复杂度都是线性的;
空间复杂度:O(N),要使用和输入数组长度相等的状态数组,因此空间复杂度是 O(N)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/103959.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DNS、ICMP和NAT

DNS、ICMP和NAT 文章目录 DNS、ICMP和NATDNS是什么域名系统的名字空间域名空间的层次结构域名的分配和管理顶级类别域名 DNS域名解析过程递归查询迭代查询 高速缓存 ICMPICMP的定位ICMP协议的功能 ICMP的报文格式ping命令traceroute命令 NATNAT技术背景NAT IP转换过程NAPTNAT的…

云原生Docker Cgroups资源控制操作

目录 资源控制 cgroups四大功能 CPU 资源控制 设置CPU使用率上限 进行CPU压力测试 设置50%的比例分配CPU使用时间上限 设置CPU资源占用比&#xff08;设置多个容器时才有效&#xff09; 设置容器绑定指定的CPU 对内存使用的限制 限制容器可以使用的最大内存 限制可用的…

“编辑微信小程序与后台数据交互与微信小程序wxs的使用“

引言 在现代移动应用开发中&#xff0c;微信小程序已经成为了一个非常流行和广泛使用的平台。为了使小程序能够展示丰富的内容和实现复杂的功能&#xff0c;与后台数据的交互是至关重要的。同时&#xff0c;微信小程序还提供了一种特殊的脚本语言——wxs&#xff0c;用于增强小…

20231024后端研发面经整理

1.如何在单链表O(1)删除节点&#xff1f; 狸猫换太子 2.redis中的key如何找到对应的内存位置&#xff1f; 哈希碰撞的话用链表存 3.线性探测哈希法的插入&#xff0c;查找和删除 插入&#xff1a;一个个挨着后面找&#xff0c;知道有空位 查找&#xff1a;一个个挨着后面找…

LeetCode 209. 长度最小的子数组

长度最小的子数组 题目链接 209. 长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度**。**如果不存在符合条件的子数组&…

【刷题-PTA】堆栈模拟队列(代码+动态图解)

【刷题-PTA】堆栈模拟队列(代码动态图解) 文章目录 【刷题-PTA】堆栈模拟队列(代码动态图解)题目输入格式:输出格式:输入样例:输出样例: 分析题目区分两栈解题思路伪代码动图演示代码测试 题目 题目描述 : 设已知有两个堆栈S1和S2&#xff0c;请用这两个堆栈模拟出一个队列Q。 …

【数据结构】线性表(十)队列:循环队列及其基本操作(初始化、判空、判满、入队、出队、存取队首元素)

文章目录 队列1. 定义2. 基本操作 顺序队列循环队列1. 头文件和常量2. 队列结构体3. 队列的初始化4. 判断队列是否为空5. 判断队列是否已满6. 入队7. 出队8. 存取队首元素9. 获取队列中元素个数10. 打印队列中的元素9. 主函数10. 代码整合 堆栈Stack 和 队列Queue是两种非常重要…

虚拟机VMware Workstation Pro安装配置使用服务器系统ubuntu-22.04.3-live-server-amd64.iso

虚拟机里安装ubuntu-23.04-beta-desktop-amd64开启SSH(换源和备份)配置中文以及中文输入法等 ​一、获取Ubuntu服务器版 获取Ubuntu服务器版 二、配置虚拟机 选择Custom(advanced)&#xff1a; 选择Workstation 17.x: 选择“I will install the operating system later.”…

I/O设备的概念和分类,I/O控制器

文章目录 1.什么是I/O设备2.按使用特性分类1.人机交互类外部设备2.存储设备3.网络通信设备 3.按传输速率分类1.低速设备:2.中速设备:3.高速设备: 4.按信息交换的单位分类1.块设备:2.字符设备: 5.I/O设备的机械部件6.I/O设备的电子部件&#xff08;I/O控制器&#xff09;1.接收和…

Vue中的加密方式(js-base64、crypto-js、jsencrypt、bcryptjs)

目录 1.安装js-base64库 2. 在Vue组件中引入js-base64库 3.使用js-base64库进行加密 4.Vue中其他加密方式 1.crypto-js 2.jsencrypt 3.bcryptjs 1.安装js-base64库 npm install js-base64 --save-dev 2. 在Vue组件中引入js-base64库 import { Base64 } from js-ba…

快速排序(c语言代码实现)

交换排序&#xff1a;快速排序&#xff08;不稳定的排序&#xff09; 快速排序&#xff08;Quick Sort&#xff09;是一种常见的排序算法&#xff0c;它采用分治法的思想&#xff0c;对待排序序列进行划分&#xff0c;使得划分出的子序列可以分别进行排序&#xff0c;最终使整…

2、Linux权限理解

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 前言 Linux权限的概念 1.文件访问者的分(人) 2.文件类型和访问权限(事物属性) 3.文件权限值的表示方法 4.文件访问权限的相关设置方法 file指令 目录的权限 粘滞位 关于权限的总结 前言 在开始Linux权限理…

python二次开发Solidworks:读取样条曲线数据

目录 1、草图段对象 2、VBA代码分析 3、python代码实现 样条曲线&#xff08;spline curve&#xff09;是数学术语&#xff0c;是一种特殊的参数曲线&#xff0c;由一组控制点通过曲线拟合的方式生成。样条一词源于船舶建造中的一种临时性辅助支架&#xff0c;后来被引入计算…

Kettle循环结果集中的数据并传入SQL组件【或转换】里面

简介&#xff1a;在尝试使用了结果集的Demo循环后&#xff0c;进入到生产还是有一点问题的&#xff0c;以下是各个组件的分解解释、遇到的问题&#xff0c;以及解决问题的思路&#xff0c;最后文章的最后会把完整的Ktr文件放出来。记得收藏点赞喔&#xff01; 先来看张图~来自…

MOTHERNEST双十一我们的目标是:不愁货——有!不愁钱——折!

喜迎双十一&#xff0c;MOTHERNEST进入开抢模式&#xff0c;水飞蓟护肝片&#xff0c;牛初乳粉&#xff0c;液体钙维生素D3胶囊将进行抢购模式&#xff0c;每人限购4件。 开抢时间&#xff1a; 2023.10.31 20:00-2023.10.31 23:59 2023.11.03 20:00-2023.11.03 23:59 限量每…

目标检测的方法

目标检测大致分为两个方向&#xff1a;基于传统的目标检测算法和基于深度学习的目标检测算法。 1.基于传统的目标检测算法 在利用深度学习做物体检测之前&#xff0c;传统算法对于目标检测通常分为3个阶段&#xff1a;区域选取、特征提取和体征分类。 2.基于深度学习的目标检测…

win10安装spark

一、进入spark下载页面 连接 Downloads | Apache Spark 二、解压下载后的.tgz文件 直接解压即可 三、运行 运行bin目录下的 spark-shell.cmd 提示 Did not find winutils.exe: java.io.FileNotFoundException: java.io.FileNotFoundException: HADOOP_HOME and hadoop.hom…

NSSCTF做题第9页(3)

[GKCTF 2020]CheckIN 代码审计 这段代码定义了一个名为ClassName的类&#xff0c;并在脚本的最后创建了一个ClassName类的实例。 在ClassName类的构造函数中&#xff0c;首先通过调用$this->x()方法获取了请求参数$_REQUEST中的值&#xff0c;并将其赋值给$this->code属性…

短视频矩阵系统软件源码

短视频矩阵系统软件源码 视频成为获得免费流量最便宜的渠道&#xff0c;平台给所有视频最基础的保底流量。如果按照一个视频最低500流量计算&#xff0c;5个账户就是2500的流量&#xff0c;200个视频就是50W流量&#xff0c;如果从其他渠道获得50W流量是个很困难的事情。短视频…

kubeadm初始化的k8s集群证书续期—— 筑梦之路

脚本自动化方式 这个是一个开源的项目&#xff1a;https://gitee.com/ximy/update-kube-cert 该项目可以自动化更新k8s集群的证书&#xff0c;使用也很简单。 该脚本可将 kubeadm 生成的证书有效期更新为 10 年。 git clone https://github.com/yuyicai/update-kube-cert.g…