暴力递归转动态规划(十)

news2024/11/18 18:26:13

题目
给定一个二维数组matrix[][],一个人必须从左上角出发,最终到达右下角,沿途只可以向下或者向右走,沿途的数字都累加就是距离累加和。返回最小距离累加和。
这道题中会采用压缩数组的算法来进行优化

暴力递归
暴力递归方法的整体思路是根据小人所在的位置(当前值),通过向下传递(向左走向右走)来获取最终选择路径的最小值。
所以base case可以确定:

  1. 如果小人走到了最后一行,那么接下来就只能向下走。
  2. 如果小人走到了最后一列,那么接下来就只能向左走。
  3. 如果小人走到了matrix[][]的最后一个格子,返回当前值给上层做处理,取最小值。
  4. 否则,既可以向左也走可以向右走,并获取最小值。

所以暴力递归的方法就出来了。

public static int minPathSum1(int[][] matrix) {

        if (null == matrix || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) {
            return -1;
        }

        int row = matrix.length;
        int col = matrix[0].length;

        return process(row - 1, col - 1, 0, 0, matrix);
    }

    //返回 matrix[i...][j....] 位置的最小值。
    public static int process(int row, int col, int curRow, int curCol, int[][] matrix) {
        //当走到最后一个位置,返回matrix中最后一个位置的值
        if (curRow == row && curCol == col) {
            return matrix[row][col];
        }
        //走到最后一行,只能往右走,只能向右累加
        if (curRow == row) {
            return matrix[curRow][curCol] + process(row, col, curRow, curCol + 1, matrix);
        }

        //走到最后一列,只能向下走
        if (curCol == col) {
            return matrix[curRow][curCol] + process(row, col, curRow + 1, curCol, matrix);
        }

        //否则,可以向右走,可以向下走,进行累加。
        int curValue = matrix[curRow][curCol];

        int p1 = curValue + process(row, col, curRow + 1, curCol, matrix);

        int p2 = curValue + process(row, col, curRow, curCol + 1, matrix);

        return Math.min(p1, p2);
    }

动态规划
这道题的动态规划也不难,给定的是一个二维数组matrix[][],每次行和列会进行变化(可变参数),所以可以创建一个和matrix大小相等的dp[][]来存放每一步计算的值。
因为只可以向下走或向右走,所以dp中任选一个格子的依赖是依赖自己的左侧的值和上面的值。其中dp中第一行的值只会依赖同行左侧的值,dp中第一列的值只会依赖同一列上面的值
所以先将dp中第一行和第一列的值填充好后,其余的按照依赖关系填充,即可完善dp表。

代码

 public static int dp(int[][] matrix) {
        if (null == matrix || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) {
            return -1;
        }

        int row = matrix.length;
        int col = matrix[0].length;
        int[][] dp = new int[row][col];

        dp[0][0] = matrix[0][0];
        for (int i = 1; i < col; i++) {
            dp[0][i] = dp[0][i - 1] + matrix[0][i];
        }

        for (int j = 1; j < row; j++) {
            dp[j][0] = dp[j - 1][0] + matrix[j][0];
        }

        for (int i = 1; i < row; i++) {
            for (int j = 1; j < col; j++) {
                dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + matrix[i][j];
            }
        }
        return dp[row - 1][col - 1];
    }

优化
动态规划方法中是创建了一个和matrix[][]大小相等的dp表,通过填充dp表来完善的代码。

如果给定的matrix[][]太大了,是不是我的dp表也要跟着很大,并且,在填充dp表时,第三行依赖第二行的值,第四行依赖第三行的值,此时。第二行的值就已经没有用了,不再需要它了,所以是不是只需要一个跟matrix[][]中列的长度相等的一维数组arr[]就够了。

先根据matrix[][]中第0行的值填充arr[],下面的两层循环中,最外层循环会让arr[0]每次加matrix中当行行的第一个值(因为只依赖上面)。内层循环,会找需要依赖的上面值(arr[j])和左边值(arr[j - 1])来取最小值,后加上matrix中当前位置上的值。

代码

 public static int minPathSum2(int[][] matrix) {
        if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) {
            return 0;
        }
        int row = matrix.length;
        int col = matrix[0].length;
        int[] arr = new int[col];
        arr[0] = matrix[0][0];
		//根据matrix第一行的值填充arr
        for (int i = 1; i < col; i++) {
            arr[i] = arr[i - 1] + matrix[0][i];
        }
        
        for (int i = 1; i < row; i++) {
            arr[0] += matrix[i][0];
            for (int j = 1; j < col; j++) {
            //arr[j - 1] : 相当于我依赖的左边
            //arr[j]  : 因为此时arr[j]的值还没修改,还是上一行的值,相当于自己的上面。 
                arr[j] = Math.min(arr[j - 1], arr[j]) + matrix[i][j];
            }
        }
        return arr[col - 1];
    }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenCV学习笔记-环境搭建

文章目录 概述下载安装Visual Studio 2022下载安装OpenCVVisual Studio 配置配置包含路径配置库路径配置链接器配置环境变量Path路径 测试C测试Python 测试 概述 OpenCV&#xff08;Open source computer vision&#xff09;是一个跨平台的计算机视觉和机器学习开源库&#xf…

C语言char与short取反以及符号判断问题

这个问题主要是在从对一个变量进行符号判断引出&#xff0c;有一种判断方法是#define ISUNSIGNED(Value) (Value >0 && ~Value >0) 主要是通过将符号位取反然后将变量与0进行比较。传入int与unsigned int结果正确&#xff0c;但是当传入unsigned char 与unsign…

差分进化算法,依旧强势

文章目录 前言DE算法DE代码DE再思考相关阅读 前言 过去两个月&#xff0c;一直在学习线性和整数规划。 今天开始&#xff0c;要回到智能优化算法了。用“回”这个字&#xff0c;主要是因为智能优化算法其实是我的老朋友了&#xff0c;毕竟在读博的大部分时间里&#xff0c;我…

论文阅读:Offboard 3D Object Detection from Point Cloud Sequences

目录 概要 Motivation 整体架构流程 技术细节 3D Auto Labeling Pipeline The static object auto labeling model The dynamic object auto labeling model 小结 论文地址&#xff1a;[2103.05073] Offboard 3D Object Detection from Point Cloud Sequences (arxiv.o…

基于springboot+vue的前后端分离房屋租赁信息网站

项目介绍 在网络高速发展的时代&#xff0c;众多的软件被开发出来&#xff0c;给用户带来了很大的选择余地&#xff0c;而且人们越来越追求更个性的需求。在这种时代背景下&#xff0c;房东只能以用户为导向&#xff0c;所以开发租房网站是必须的。 系统采用了Java技术&#x…

爬虫 | 【实践】Best Computer Science Scientists数据爬取

文章目录 &#x1f4da;数据需求&#x1f4da;数据爬取&#x1f407;排行榜页数据爬取&#x1f407;获取详情页&#x1f407;目标信息提取 &#x1f4da;完整代码与结果 &#x1f4da;数据需求 姓名&#xff0c;国家&#xff0c;学校 最有名研究领域 目前研究领域 共同作…

16 | 如何自定义 HandlerMethodArgumentResolvers

上一讲我们介绍了 SpringDataWebConfiguration 类的用法&#xff0c;那么这次我们来看一下这个类是如何被加载的&#xff0c;PageableHandlerMethodArgumentResolver 和 SortHandlerMethodArgumentResolver 又是如何生效的&#xff0c;以及如何定义自己的 HandlerMethodArgumen…

c语言练习89:链表的使用

链表的使用 虽然有这么多的链表的结构&#xff0c;但是我们实际中最常⽤还是两种结构&#xff1a; 单链表 和 双向带头循环链表 1. ⽆头单向⾮循环链表&#xff1a;结构简单&#xff0c;⼀般不会单独⽤来存数据。实际中更多是作为其他数据结 构的⼦结构&#xff0c;如哈希桶、…

数据结构与算法—单链表

目录 一、链表 1、链表的概念及结构 2、分类 二、实现单向链表 1、声明链表结构体 2、输出 3、头插&尾插 4、头删尾删 5、查找 6、指定位置插入 7、删除指定节点 8、删除指定节点的后一个节点 9、单链表的销毁 完整版 LList.h LList.c text.c 一、链表 …

Go错误处理方式真的不好吗?

平时经常上一些网络平台阅读一些技术讨论的话题&#xff0c;对Go语言方面也有些浅浅的关注&#xff0c;正如标题所问&#xff0c;Go语言错误处理可以说算是网络上开发中对Go语言吐槽最多的点之一&#xff0c;那么&#xff0c;Go错误处理真的很不堪吗&#xff1f; 对此我认为&a…

CANoe制作网关实现CAN(FD)报文故障注入(报文长度/timeout/信号错误/E2E)1

CANoe制作网关实现CAN报文故障注入&#xff08;报文长度/timeout/信号错误/E2E&#xff09; 文章目录 CANoe制作网关实现CAN报文故障注入&#xff08;报文长度/timeout/信号错误/E2E&#xff09;1.基本介绍和实现功能 1.基本介绍和实现功能 下面是一个完整的CAN/CANFD总线&…

【Wifi】Wifi架构介绍

Wifi架构介绍 本文基于Android介绍其Wifi架构。Wifi是许多操作系统提供的重要功能之一&#xff0c;特别是越来越多的车载系统wifi是其必备功能。为啥wifi是必备功能&#xff1f; 一方面是传统的上网&#xff08;现在有些车载使用DCM模块管理网络&#xff09;&#xff0c;另一方…

项目管理软件中注释功能的作用是什么?

在项目管理软件中&#xff0c;注释功能允许您对任务、文件夹和项目进行详细的标注。这一功能不仅便于团队成员之间的沟通与协作&#xff0c;还能提高项目管理的效率。通过在项目中添加评论&#xff0c;您可以及时了解项目的最新动态&#xff0c;提出疑问并寻求解决方案。此外&a…

【大模型应用开发教程】01_大模型简介

C1 大模型简介 一. 什么是LLM&#xff08;大语言模型&#xff09;&#xff1f;1. 发展历程2. 大语言模型的概念LLM的应用和影响 二、大模型的能力和特点1. 大模型的能力1.1 涌现能力&#xff08;emergent abilities&#xff09;1.2 作为基座模型支持多元应用的能力1.3 支持对话…

AN基础工具——填色工具

【AN基础工具——填色工具】 基本使用方法填色补充给色块周围画上线 变色动画渐变变色的蜥蜴 本篇内容&#xff1a;填色动画制作 重点内容&#xff1a;填色工具 工 具&#xff1a;Adobe Animate 2022 基本使用方法 填色补充 之前说图形要封闭才能填色&#xff0c;实际情况是有…

ESP8266 Node Mcu开发板连接WIFI并上报数据到MQTT服务器——物联网应用开发

一、前言 本文主要介绍关于ESP8266 Node Mcu开发板如何连接WIFI并将本地采集的数据上传到MQTT服务器中。 大家调试可以使用MQTTBox 二、WIFI连接 首先&#xff0c;导入WIFI连接所需的头文件&#xff0c;引入所需库。 #include <ESP8266WiFi.h> 声明字符串常量&#xff0…

3.1 模板测试与深度测试(Stencil Test Z Test)

一、模板测试&#xff08;Stencil Test&#xff09; 模板测试可以实现的一些效果图 1.是什么 ①从渲染管线出发&#xff1a;模板测试是在逐片源操作阶段&#xff0c;透明测试之后&#xff0c;深度测试之前的位置。 ②从书面概念上理解 说到模板测试&#xff0c;就要先说道模…

Java设计模式-结构性设计模式(享元设计模式)

简介 属于结构型模式&#xff0c;主要⽤于减少创建对象的数量&#xff0c;以减少内存占⽤和提⾼性能&#xff0c; 它提供了减少对象数量从⽽改善应⽤所需的对象结构的⽅式享元模式尝试重⽤现有的同类对象&#xff0c;如果未找到匹配的对象&#xff0c;则创建新对象应用场景 JAV…

C语言天花板——指针(进阶1)

接上次的指针初阶&#xff08;http://t.csdnimg.cn/oox5s&#xff09;&#xff0c;这次我们继续的探寻指针的奥秘&#xff0c;发车咯&#xff01;&#xff01;&#xff01;&#x1f697;&#x1f697;&#x1f697; 一、字符指针 可以看到我们将指针p给打印出来&#xff0c;就是…

LDA(Fisher)线性判别分析

LDA&#xff08;Fisher&#xff09;线性判别分析 对于二分类问题若存在一个 y i W x i y_iWx_i yi​Wxi​将样本 X \pmb X X投影到一维空间上 为了使两个样本能够较好的分开&#xff0c;应该是的每一个同类的样本的方差&#xff08;离散程度&#xff09;尽可能的小&#xff0…