力扣动态规划基础版(矩阵型)

62.不同路径(唯一路径问题)

62. 不同路径icon-default.png?t=O83Ahttps://leetcode.cn/problems/unique-paths/

方法一:动态规划 

 找状态转移方程,也就是说它从左上角走到右下角,只能往右或者往下走,那么设置一个位置为(i,j)它只能从(i-1,j)或者(i,j-1)走过来那么它的状态转移方程就是除了这个还要去思考边界条件,如果i=0那么就不满足右侧的状态转移方程,同理j

= 0也不行,就是边上的那些数,可以考虑到边上的那些数都可以设置为1,也就是f(i,0)和f(0,j)都是1

class Solution {
    public int uniquePaths(int m, int n) {
    int[][] f = new int [m][n];
    for(int i = 0; i < m; i ++){
        f[i][0] = 1;
    }
    for(int j = 0; j < n ; j++){
        f[0][j] = 1;
    }
    for(int i = 1; i < m; ++i){
        for(int j = 1; j < n; ++j){
            f[i][j] = f[i -1][j]  + f[i][j -1];
        }
    }
    return f[m - 1][n - 1];
    }
}

优化空间复杂度:

这个唯一路径问题可以进行空间复杂度的优化 :由于 f(i,j) 仅与第 i 行和第 i−1 行的状态有关,因此我们可以使用滚动数组代替代码中的二维数组,使空间复杂度降低为 O(n)。

这个思路是。我们不需要存储每一个点,只需要存储它的上面一个点就行,再加上上一列的值即可,从第二行开始,每一行进行遍历只需要原始的值加上上一列的值。边界条件就是第一行都是1(很好想)

class Solution {
    public int uniquePaths(int m, int n) {
        //对于每一行,按列进行遍历
        //第一行先都设为1
        int f[] = new int[n];
        for(int i = 0; i < n; ++i){
            f[i] = 1;
        }
        //从第二行开始,对每一列进行遍历,它的f值只和它的前一列相关
        for(int i = 1; i < m; i++){
            for(int j = 1; j < n; j++){
                f[j]  += f[j - 1];//这个f[j]再每一次行遍历都更新,它就代表着上一次遍历的上一行的内容 
            }
        }
        return f[n - 1];
    }
}

方法二:排列组合

因为它只能向下走或者是向右走,所以就只有

从左上角到右下角的过程中,我们需要移动 m+n−2 次,其中有 m−1 次向下移动,n−1 次向右移动。因此路径的总数,就等于从 m+n−2 次移动中选择 m−1 次向下移动的方案数。实现这个排列组合的式子就行,其实实现这个技巧也是有讲究的,因为上面等于下面两个的和,所以位数是一样的,做一个循环,每一项相乘就行

class Solution {
    public int uniquePaths(int m, int n) {
        long ans = 1;
        for(int x =  n,y = 1; y < m; ++x,++y){
            ans = ans *x/y;
        }
        return (int)ans;
    }
}

64.最小路径和 

64. 最小路径和icon-default.png?t=O83Ahttps://leetcode.cn/problems/minimum-path-sum/还不错这道题自己写出来了,感觉就是前面那个题目的变式,状态转移方程就是第(i,j)个点的最小值由于只能向下或者向右,所以最小值就是它上面的或者左边的加上它自身的值。然后边界条件考虑(0,0),再考虑第一行和第一列。

class Solution {
    public int minPathSum(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        int dp[][] = new int [m][n];
        dp[0][0] = grid[0][0];
        for(int i = 1 ; i < m ;++i){
            dp[i][0] = dp[i -1][0] + grid[i][0];
        }
        for(int j = 1; j < n;++j){
            dp[0][j] = dp[0][j - 1] + grid[0][j];
        }
        for(int i = 1; i < m; i++){
            for(int j = 1; j < n; j++){
                dp[i][j] = grid[i][j] + Math.min(dp[i -1][j],dp[i][j - 1]);
            }
        }
        return dp[m -1][n -1];
    }
}

63.不同路径Ⅱ

63. 不同路径 IIicon-default.png?t=O83Ahttps://leetcode.cn/problems/unique-paths-ii/

这个其实大同小异,但是加了个障碍也就是说带障碍的要做个判断,如果他这是0,这条路就死了直接置为0

然后这次构建dp数组是多了一个空间确实好用 

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        int dp[][] = new int [m+1][n+1];
        dp[1][1] = 1;
        for(int i = 1; i < m + 1; ++i){
            for(int j = 1;j < n + 1; ++j){
                if(obstacleGrid[i -1][j -1] == 1){
                    dp[i][j] = 0;
                }
                else{
                    dp[i][j] = Math.max(dp[i][j],dp[i - 1][j]+dp[i][j -1]);//这里的max是为了dp[1][1]
                }
            }
        }
        return dp[m][n];
    }
}

做完了这个题我又回头看第62题,确实是这样创建数组更舒服,我就又写了一版62的题解

class Solution {
    public int uniquePaths(int m, int n) {
    int[][] f = new int [m + 1][n + 1];
    f[1][1] = 1;
    for(int i = 1; i < m + 1; ++i){
        for(int j = 1; j < n + 1; ++j){
            f[i][j] = Math.max(f[i -1][j]  + f[i][j -1],f[i][j]);
        }
    }
    return f[m][n];
    }
}

对于63题我觉得不能用这钟方式,因为如果这样设置他的转移方程是求最小值,这样的话边界是0的情况下都算进去了,就错误了。

120.三角形最小路径和

方法一:动态规划 

120. 三角形最小路径和icon-default.png?t=O83Ahttps://leetcode.cn/problems/triangle/看到这个题目有点恍惚了,感觉是和以前的题目没啥区别,状态转移方程也是很好想,就是这一个的最小值就是上面和上面的左边的最小值加上这个值的min,但是三角形边界的情况还是特殊一点,因为就是比如在第i行的第0个发现j-1到达不了,以及在第i行的第i个发现在第i-1行的第i列也到达不了,所以要考虑这个两边的边界情况。其他的部分还是很像的,还需注意的是triangle是数组想取值用get

 for(int i = 1; i < m; ++i){
            dp[i][0] = dp[i -1][0] + triangle.get(i).get(0);
            for(int j =1;j < i; ++j){
                dp[i][j] = Math.min(dp[i -1][j -1],dp[i -1][j]) +triangle.get(i).get(j);
            }
            dp[i][i] = dp[i - 1][i - 1] + triangle.get(i).get(i);
        }

class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        int m = triangle.size();
        int [][] dp = new int [m][m];
        dp[0][0] = triangle.get(0).get(0);
        for(int i = 1; i < m; ++i){
            dp[i][0] = dp[i -1][0] + triangle.get(i).get(0);
            for(int j =1;j < i; ++j){
                dp[i][j] = Math.min(dp[i -1][j -1],dp[i -1][j]) +triangle.get(i).get(j);
            }
            dp[i][i] = dp[i - 1][i - 1] + triangle.get(i).get(i);
        }
        int minTol = dp[m -1][0];
        for(int i = 1; i < m; i++){
            minTol = Math.min(minTol,dp[m -1][i]);
        }
        return minTol;
    }
}

931.下降路径最小和

931. 下降路径最小和icon-default.png?t=O83Ahttps://leetcode.cn/problems/minimum-falling-path-sum/这道题目其实和上一道的思路属于是殊途同归的,需要考虑这些形状的边界的情况,与三角形不同,这个要考虑左右两边,容易出错的点就是在考虑右边的时候注意下标m -1同时考虑最后一排的最小值。做过上面那道题,这道题可以轻松ac

class Solution {
    public int minFallingPathSum(int[][] matrix) {
        int m = matrix.length;
        int dp[][]  = new int [m][m];
        //初始化
        for(int i = 0; i < m; ++i){
            dp[0][i] = matrix[0][i];
        }
        for(int i = 1; i < m; ++i){
            dp[i][0] = matrix[i][0] + Math.min(dp[i - 1][0],dp[i -1][1]); 
            for(int j = 1; j < m - 1; ++j){
                dp[i][j] = matrix[i][j] + Math.min(Math.min(dp[i -1][j -1],dp[i -1][j]),dp[i -1][j + 1]);
            }
            dp[i][m - 1] = matrix[i][m -1] + Math.min(dp[i -1][m -1],dp[i -1][m -2]);
        }
        int minres = dp[m -1][0];
        for(int i = 0; i < m; ++i){
             minres = Math.min(minres,dp[m -1][i]);
        }
        return minres;
    }
}

221.最大正方形 

221. 最大正方形icon-default.png?t=O83Ahttps://leetcode.cn/problems/maximal-square/

方法一:暴力

暴力来说的话还是比较好想的,就是先遍历一遍,如果有1就设置为res为1了,然后就找到这个左上角,去算一下潜在的最大正方形,再去遍历去找,先沿着对角线如果是1的话,就再看看其他地方是否满足,设置flag,如果不满足置为false

class Solution {
    public int maximalSquare(char[][] matrix) {
        int m = matrix.length;int n = matrix[0].length;
        int res = 0;
        if(matrix == null || matrix.length == 0 || matrix[0].length == 0){
            return res;
        }
        for(int i = 0; i < m; ++i){
            for(int j = 0; j < n; ++j){
                if(matrix[i][j] == '1'){
                    res = Math.max(1,res);
                    //计算可能的最大的正方形边长
                    int currentMaxside = Math.min(m - i,n - j);
                    for(int k = 1 ;k < currentMaxside; ++k){
                       //判断新增的一列是否都是1
                       boolean flag = true; 
                       if(matrix[i + k][j + k] == '0'){
                        break;
                       }
                       for(int q = 0; q < k; ++q){
                        if(matrix[i + k][j + q] == '0' || matrix[i + q][j + k] == '0'){
                            flag = false;
                            break;
                        }
                       }
                        if(flag){
                            res = Math.max(res,k + 1);
                        }
                        else{
                            break;
                        }
                    }
                }
            }
        }
        int ress = res * res;
        return ress;
    }
}

方法二:动态规划

这个就有点秒了,考虑的是用 dp(i,j) 表示以 (i,j) 为右下角,且只包含 1 的正方形的边长最大值。

如果该位置的值是 1,则 dp(i,j) 的值由其上方、左方和左上方的三个相邻位置的 dp 值决定。具体而言,当前位置的元素值等于三个相邻位置的元素中的最小值加 1。

这样的话状态转移方程就可以用下面式子来表示

然后注意边界条件就是,如果在第一排或者第一列,瑞国他是1的话,dp[i][j]只能为1 

dp[i][j] = Math.min(Math.min(dp[i -1][j],dp[i - 1][j -1 ]),dp[i][j -1]) + 1
class Solution {
    public int maximalSquare(char[][] matrix) {
        int Maxres = 0;
        int rows = matrix.length;
        int 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 - 1][j -1 ]),dp[i][j -1]) + 1;
                    }
                Maxres = Math.max(Maxres,dp[i][j]);
                }
            }
        }
        int Maxsquare = Maxres * Maxres;
        return Maxsquare;
    }
}

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

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

相关文章

Ubuntu 22 安装 Apache Doris 3.0.3 笔记

Ubuntu 22 安装 Apache Doris 3.0.3 笔记 1. 环境准备 Doris 需要 Java 17 作为运行环境&#xff0c;所以首先需要安装 Java 17。 sudo apt-get install openjdk-17-jdk -y sudo update-alternatives --config java在安装 Java 17 后&#xff0c;可以通过 sudo update-alter…

141/142题环形链表

本题返回环入口的位置。使用快慢指针&#xff0c;快指针每次移动两个&#xff0c;慢指针每次移动一个。设前一段距离是a,进入环内到slow和fast相遇的地点距离是b&#xff0c;环内剩下的距离是c&#xff0c;如图所示。 环的长度是bc 慢指针移动距离是ab 快指针移动距离是abk(bc…

leetcode25:k个一组链表反转

给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内部的值…

《今日制造与升级》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答 问&#xff1a;《今日制造与升级》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的正规学术期刊。 问&#xff1a;《今日制造与升级》级别&#xff1f; 答&#xff1a;国家级。主管单位&#xff1a;中国机械工业联合会 …

【Linux第八课-进程间通信】管道、共享内存、消息队列、信号量、信号、可重入函数、volatile

目录 进程间通信为什么&#xff1f;是什么&#xff1f;怎么办&#xff1f;一般规律具体做法 匿名管道原理代码 命名管道原理代码 system V共享内存消息队列信号量信号量的接口 信号概念为什么&#xff1f;怎么办&#xff1f;准备信号的产生信号的保存概念三张表匹配的操作和系统…

C++builder中的人工智能(18):神经网络中的SoftMax函数

在这篇文章中&#xff0c;我们将探讨SoftMax函数在神经网络中的作用&#xff0c;如何在人工神经网络&#xff08;ANN&#xff09;中使用SoftMax函数&#xff0c;以及在AI技术中SoftMax的应用场景。让我们来详细解释这些概念。 SoftMax函数是什么&#xff1f; SoftMax函数是逻辑…

证件照尺寸168宽240高,如何手机自拍更换蓝底

在提供学籍照片及一些社会化考试报名时&#xff0c;会要求我们提供尺寸为168*240像素的电子版证件照&#xff0c;本文将介绍如何使用“报名电子照助手”&#xff0c;借助手机拍照功能完成证件照的拍摄和背景更换&#xff0c;特别是如何将照片尺寸调整为168像素宽和240像素高&am…

pytest+request+allure接口自动化框架搭建分享

介绍分享一个接口自动化框架搭建方法 (pytestrequestallure)&#xff0c;这个方案是由 xpcs 同学在TesterHome社区网站的分享。 写在前面 去年11月被裁&#xff0c;到现在还没上岸&#xff0c;gap 半年了。上岸无望&#xff0c;专业技能不能落下&#xff0c;花了两三天时间&…

大数据新视界 -- 大数据大厂之 Impala 性能优化:融合机器学习的未来之路(上 (2-2))(11/30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

Unity 实现数字垂直滚动效果

Unity 实现数字垂直滚动效果 前言项目场景布置Shader代码编写材质球设置代码编写数字图片 前言 遇到一个需要数字垂直滚动模拟老虎机的效果&#xff0c;记录一下。 项目 场景布置 3个Image换上带有RollNumberShader的材质 在RollNumberScript脚本中引用即可 Shader代码编…

[linux]docker基础

常见命令 Docker最常见的命令就是操作镜像、容器的命令&#xff0c;详见官方文档: Docker Docs 案例: 查看DockerHub&#xff0c;拉取Nginx镜像&#xff0c;创建并运行Nginx容器 在DockerHub中搜索Nginx镜像 拉取Nginx镜像 查看本地镜像列表 把镜像保持到本地 查看保持命令的…

纯C++信号槽使用Demo (sigslot 库使用)

sigslot 库与QT的信号槽一样&#xff0c;通过发送信号&#xff0c;触发槽函数&#xff0c;信号槽不是QT的专利&#xff0c;早在2002年国外的一小哥用C写了sigslot 库&#xff0c;简单易用&#xff1b; 该库的官网&#xff08;喜欢阅读的小伙伴可以仔细研究&#xff09;&#xf…

(Go语言)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法

0. 序言 从这章开始&#xff0c;在Go基础语法里难度就开始上来了 在学习函数与方法前&#xff0c;先弄明白指针是很重要的。 1. 指针 在没学指针前&#xff0c;相信很多人就已经大概知道指针是个什么东西了。因为它太有名了&#xff0c;当然是与 C和C 的出名有关。 1.1 指针…

基于redis实现API接口访问次数限制

一&#xff0c;概述 日常开发中会有一个常见的需求&#xff0c;需要限制接口在单位时间内的访问次数&#xff0c;比如说某个免费的接口限制单个IP一分钟内只能访问5次。该怎么实现呢&#xff0c;通常大家都会想到用redis&#xff0c;确实通过redis可以实现这个功能&#xff0c…

实在智能受邀出席柳州市智能终端及机器人产业发展合作大会

10 月 27 日至 28 日&#xff0c;由中共柳州市委员会与柳州市人民政府主办的2024柳州市智能终端及机器人产业发展合作大会在柳州莲花山庄隆重举行。大会充分整合各方资源&#xff0c;持续深化与柳州在重大战略规划、重大平台建设、重点产业培育等领域的合作。作为智能体行业的知…

JDBC-PreparedStatement

在前面使用的Statement中&#xff0c;编写sql语句使用的是拼接的形式&#xff0c;这样不仅可读性差&#xff0c;还非常容易导致出错&#xff0c;最大的问题是安全问题。 sql注入 在需要用户输入的地方&#xff0c;用户输入的是SQL语句的片段&#xff0c;最终用户输入的SQL片段…

如何创建备份设备以简化 SQL Server 备份过程?

SQL Server 中的备份设备是什么&#xff1f; 在 SQL Server 中&#xff0c;备份设备是用于存储备份数据的物理或逻辑介质。备份设备可以是文件、设备或其他存储介质。主要类型包括&#xff1a; 文件备份设备&#xff1a;通常是本地文件系统中的一个或多个文件。可以是 .bak 文…

非计算机背景但是想从事医学AI研究,需要掌握的编程语言|个人观点·24-11-08

小罗碎碎念 目前&#xff0c;我们从事医学AI研究的&#xff0c;接触的最多的两种编程语言应该就是R和Python了。那么初学者很容易提出一个疑问&#xff0c;**我想从事医学AI相关的研究的话&#xff0c;应该学哪些编程语言呢&#xff1f;**在文章的开头&#xff0c;我可以先给出…

Jmeter基础篇(21)教你手动修改Jmeter测试报告和压测结果

哈喽呀各位小伙伴!今天给大家带来一期关于Jmeter黑科技的教学! 在日常性能测试过程中,我们经常使用JMeter这个强大的工具来执行压力测试,并通过JMeter的报告生成命令,从CSV或JTL文件中读取数据,生成HTML格式的测试报告。然而,测试报告生成之后,数据就是固定的了,很多…

AHB Matrix 四星级 验证笔记(2.4) Tt3.3AHB总线协议测试时的 并行数据

文章目录 前言一、代码二、错误1.地址范围2. 并行执行线程中变量覆盖的情况3.有关incr的beat 前言 来源路科验证本节搞定 T3.3 AHB总线协议的覆盖&#xff1a;AHB_PROTOCOL_COVER 即测试ahb slave接口和master接口支持&#xff08;尽可能&#xff09;全部的ahb协议传输场景&am…