[100天算法】-不同路径(day 37)

news2024/9/28 23:30:07

题目描述

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

问总共有多少条不同的路径?

例如,上图是一个7 x 3 的网格。有多少可能的路径?


示例 1:

输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。

向右 -> 向右 -> 向下
向右 -> 向下 -> 向右
向下 -> 向右 -> 向右
示例 2:
输入: m = 7, n = 3
输出: 28


提示:

1 <= m, n <= 100
题目数据保证答案小于等于 2 * 10 ^ 9

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-paths
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

方法 1:递归(TLE)

思路

首先是直觉的递归法。

  • 在每个格子我们都有两个选择:向右走向下走
  • 如果走到了网格最右侧的那一列,我们就只剩下 向下走 这个选项
  • 如果走到了网格最底下的那一行,我们就只剩下 向右走 这个选项
  • 所以在每个格子做选择之前,先要判断能不能向右/向下走
  • 等走到最后一个格子,在这个格子我们既不能向右也不能向下,就在记录上加一

代码

JavaScript Code

/**
 * @param {number} m
 * @param {number} n
 * @return {number}
 */
var uniquePaths = function (m, n) {
    let total = 0;
    dfs(m, n, 0, 0);
    return total;

    // ***********************************

    function dfs(m, n, row, col) {
        if (row === n - 1 && col === m - 1) {
            total++;
            return;
        }
        row < n - 1 && dfs(m, n, row + 1, col);
        col < m - 1 && dfs(m, n, row, col + 1);
    }
};

更简洁的递归版:

JavaScript Code

/**
 * @param {number} m
 * @param {number} n
 * @return {number}
 */
var uniquePaths = function (m, n) {
    if (m === 1 || n === 1) return 1;
    return uniquePaths(m - 1, n) + uniquePaths(m, n - 1);
};

复杂度分析

  • 时间复杂度:$O(2^max(m, n))$,2 是递归树的最大分支数,因为在每个函数中都有两次递归调用,指数部分是树的最大深度。
  • 空间复杂度:$O(max(m, n))$,递归树的最大深度。

方法 2:动态规划

思路

我们的目标是走到网格右下角的格子,不妨假设我们已经走到了这个格子,那往前推一步,走到这个格子之前我们在哪呢?只能是它左边或者上方的格子。

  • 假设我们已经知道了有多少条路径可以走到它左边的格子,用 F(left) 来表示;
  • 假设我们也已知道了有多少条路径可以走到它上方的格子,用 F(top) 来表示;

那我们很容易就能算出,要走到右下角的格子,一共有 F(bottomRight) = F(left) + F(top) 条路径。

我们可以从右下角的格子一直往前推,计算每个格子的状态 F(cell) = F(left) + F(top)。直到,退到起点,因为我们已经站在起点了,也就是说只有一条路,所以 F(topLeft) = 1

现在我们再把这个过程反过来,从起点开始,一直往右下角的格子前进,一路算出走到每个格子有多少条路径 F(cell),最终就可以得到我们想要的结果 F(bottomRight) 了。

因为要记录每个格子的状态,所以需要一个二维数组

代码

TypeScript Code

function uniquePaths(m: number, n: number): number {
    const dp: number[][] = Array(n + 1)
        .fill(0)
        .map(() => Array(m + 1).fill(0));
    dp[1][1] = 1;

    for (let i = 1; i <= n; i++) {
        for (let j = 1; j <= m; j++) {
            dp[i][j] = dp[i][j] + dp[i - 1][j] + dp[i][j - 1];
        }
    }

    return dp[n][m];
}

Python Code

class Solution(object):
    def uniquePaths(self, m, n):
        """
        :type m: int
        :type n: int
        :rtype: int
        """
        dp = [[0] * (m) for _ in range(n)]

        for i in range(n):
            dp[i][0] = 1
        for j in range(m):
            dp[0][j] = 1

        for i in range(1, n ):
            for j in range(1, m):
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1]

        return dp[n - 1][m - 1]

复杂度分析

  • 时间复杂度:$O(m*n)$。
  • 空间复杂度:$O(m*n)$。

动态规划(空间优化版)

思路

因为每个格子只依赖它左边上边的格子的状态,所以我们没必要用二维数组来存储整个网格的状态,只需要两个一维数组:一个存上一行格子的状态,一个存当前行格子的状态,然后在遍历的过程中更新这两个数组就好了。

代码

TypeScript Code

function uniquePaths(m: number, n: number): number {
    let last: number[] = Array(m + 1).fill(0);
    last[1] = 1;
    for (let i = 1; i <= n; i++) {
        const cur = Array(m + 1).fill(0);
        for (let j = 1; j <= m; j++) {
            cur[j] = cur[j - 1] + last[j];
        }
        last = cur;
    }
    return last[m];
}

复杂度分析

  • 时间复杂度:$O(m*n)$。
  • 空间复杂度:$O(n)$。

相似题目 - 63. 不同路径 II

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

思路

跟 62 题差不多,只是如果当前格子有障碍的话,就把 dp[i][j] 重置为 0,说明此路不通。

代码

动态规划:

JavaScript Code

/**
 * @param {number[][]} obstacleGrid
 * @return {number}
 */
var uniquePathsWithObstacles = function (obstacleGrid) {
    const rows = obstacleGrid.length;
    const cols = obstacleGrid[0].length;
    const dp = Array(rows + 1)
        .fill(0)
        .map(() => Array(cols + 1).fill(0));
    dp[1][1] = 1;

    for (let i = 1; i <= rows; i++) {
        for (let j = 1; j <= cols; j++) {
            if (obstacleGrid[i - 1][j - 1] === 1) {
                dp[i][j] = 0;
            } else {
                dp[i][j] = dp[i][j] + dp[i - 1][j] + dp[i][j - 1];
            }
        }
    }
    return dp[rows][cols];
};

空间优化:

JavaScript Code

/**
 * @param {number[][]} obstacleGrid
 * @return {number}
 */
var uniquePathsWithObstacles = function (obstacleGrid) {
    const rows = obstacleGrid.length;
    const cols = obstacleGrid[0].length;

    let prev = Array(cols + 1).fill(0);
    prev[1] = obstacleGrid[0][0] === 1 ? 0 : 1;
    let cur = Array(cols + 1).fill(0);

    for (let i = 1; i <= rows; i++) {
        for (let j = 1; j <= cols; j++) {
            if (obstacleGrid[i - 1][j - 1] === 1) {
                cur[j] = 0;
            } else {
                cur[j] = cur[j - 1] + prev[j];
            }
        }
        [prev, cur] = [cur, prev];
    }
    return prev[cols];
};

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

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

相关文章

MATLAB | 两种上色方式的旭日图绘制

嘿&#xff0c;这次真的是好久不见了&#xff0c;好不容易才有点空写点文章&#xff0c;这段时间忙到后台回复都有点来不及看&#xff0c;很抱歉有一部分后台留言刚看到就已经超过时限没法回复了&#xff0c;不过根据大家的留言&#xff0c;需求主要集中在希望出一期旭日图的教…

12、Python -- if 分支 的讲解和使用

目录 程序结构顺序结构分支结构分支结构注意点不要忘记冒号 if条件的类型if条件的逻辑错误if表达式pass语句 程序流程 分支结构 分支结构的注意点 if条件的类型 if语句的逻辑错误 if表达式 程序结构 Python同样提供了现代编程语言都支持的三种流程 顺序结构 分支结构 循环结构…

CPU核检测

import psutil num_cpus psutil.cpu_count(logicalFalse) print(num_cpus) num_cpus psutil.cpu_count(logicalTrue) print(num_cpus)结果如下 可以看到这个结果是不同的

fiddler导出录制脚本并导出jmter脚本文件

1、fiddler导出录制脚本 可以通过save保存录制的脚本&#xff1a; 也可以选中这些链接&#xff0c;点击右键-->save-->select sessions -->选择要导入的文件 2、导入录制的脚本 再fiddler-->file--->load ARCHIVERS--->选择刚导出的.saz文件&#xff0c;正…

01-初识VUE3

01.初识VUE3 1.创建VUE3项目 1).使用 vue-cli 创建 ## 查看vue/cli版本&#xff0c;确保vue/cli版本在4.5.0以上 vue --version ## 安装或者升级你的vue/cli npm install -g vue/cli ## 创建 vue create vue_test ## 启动 cd vue_test npm run serve2).使用 vite 创建 ## 创…

吃豆人C语言开发—Day2 需求分析 流程图 原型图

目录 需求分析 流程图 原型图 主菜单&#xff1a; 设置界面&#xff1a; 地图选择&#xff1a; 游戏界面&#xff1a; 收集完成提示&#xff1a; 游戏胜利界面&#xff1a; 游戏失败界面 死亡提示&#xff1a; 这个项目是我和朋友们一起开发的&#xff0c;在此声明一下…

【C#】委托与事件

目录 一、委托 1.什么是委托 2.委托类型的声明与初始化 3.委托类型引用方法的调用 4.使用委托类型作为方法的参数 5.Action委托 6.Func委托 7.通用类型冒泡排序 8.多播委托 二、Lambda表达式 1.匿名方法 2.Lambda表达式表示匿名方法 三、事件 1.什么是事件 2.事件…

Django viewsets 视图集与 router 路由实现评论接口开发

正常来说遵循restful风格编写接口&#xff0c;定义一个类包含了 get post delete put 四种请求方式&#xff0c;这四种请求方式是不能重复的 例如:获取单条记录和多条记录使用的方式都是get&#xff0c;如果两个都要实现的话那么得定义两个类&#xff0c;因为在同一个类中不能有…

【vue3 】 创建项目vscode 提示无法找到模块

使用命令创建 vue3 创建新应用 npm create vuelatest会看到一些可选功能的询问&#xff1f; √ 请输入项目名称&#xff1a; … vue-project √ 是否使用 TypeScript 语法&#xff1f; … 否 / 是 √ 是否启用 JSX 支持&#xff1f; … 否 / 是 √ 是否引入 Vue Router 进行单…

useReducer的使用以及与useState、useImmerReducer的对比使用

前言 对于拥有许多状态更新逻辑的组件来说&#xff0c;过于分散的事件处理程序可能会影响代码的可读性。这种情况&#xff0c;可以将组件的所有状态更新逻辑整合到一个外部函数中&#xff0c;这个函数就是reducer。 使用 useReducer(reducer, initialArg, init?) 参数 redu…

电力通信与泛在电力物联网技术的应用与发展-安科瑞黄安南

摘要&#xff1a;随着我国社会经济的快速发展&#xff0c;我国科技实力得到了非常大的提升&#xff0c;当前互联网通信技术在社会中得到了广泛的应用。随着电力通信技术的快速发展与更新&#xff0c;泛在电力物联网建设成为电力通讯发展的重要方向。本文已泛在电力物联网系统为…

化工园区数字孪生可视化管控平台,赋予园区安全环保智慧发展

化工行业作为国民经济的支柱和工业发展的引擎&#xff0c;对安全生产、环保节能、应急管控有着很高的要求。目前国内外化工园区面临安全和环保两大压力。为有效解决这两大难题&#xff0c;巨蟹数科综合运用物联网、数字孪生等新一代信息技术&#xff0c;建设了数字孪生园区智慧…

Docker下安装MSSQL并使用Navicat远程连接(备忘录)

Docker下安装MSSQL并使用Navicat远程连接 一. Docker下安装MSSQL备忘录一、安装SQL Server1、从 Microsoft 容器注册表中请求 SQL Server 2022 (16.x) Linux 容器映像:注意:2、运行这个cu5的版本下表对前一个 docker run 示例中的参数进行了说明:3、看这个MSSQL运行没有?用…

JAVA基础——编译器报告的错误信息总结

1. Invalid character&#xff08;无效字符&#xff09; 中英文符号错误 2. 数组的常见异常 数组越界异常ArrayIndexOutOfBoundsException: 在使用索引访问数组的元素时超出了数组的索引范围0~length-1。 空指针异常NullPointerException&#xff1a; 在使用变量引用一个数…

CSS - 常用属性和布局方式

目录 前言 一、常用属性 1.1、字体相关 1.2、文本相关 1.3、背景相关 1.3.1、背景颜色 1.3.2、背景图片 1.4、圆角边框 二、常用布局相关 2.1、display 2.2、盒子模型 2.2.1、基本概念 2.2.2、border 边框 2.2.3、padding 内边距 2.2.4、margin 外边距 2.3、弹…

【Android】MQTT

目录 MQTT 协议简介应用场景优点缺点 部署服务端下载安装包启动服务器 搭建客户端下载SDK添加依赖配置MQTT服务和权限建立连接订阅主题发布消息取消订阅断开连接 MQTT客户端工具最终效果实现传感器数据采集与监测功能思路 MQTT 协议 简介 MQTT&#xff08;Message Queuing Te…

【目标跟踪】多目标跟踪测距

文章目录 前言python代码&#xff08;带注释&#xff09;main.pysort.pykalman.pydistance.py 结语 前言 先放效果图。目标框内左上角&#xff0c;显示的是目标距离相机的纵向距离。目标横向距离、速度已求出&#xff0c;没在图片展示。这里不仅仅实现对目标检测框的跟踪&#…

【Django restframework】django跨域问题,解决PUT/PATCH/DELETE用ajax请求无法提交数据的问题

【Django restframework】django跨域问题&#xff0c;解决PUT/PATCH/DELETE用ajax请求无法提交数据的问题 1 问题描述&#xff1a; 我用restframework(ModelSerializerGenericApiView)开发了一组符合RestFul接口标准的接口&#xff0c;这意味着它将支持客户端发来的GET、POST、…

矢量图形编辑软件 illustrator 2023 mac 中文软件特点

illustrator 2023 mac是一款矢量图形编辑软件&#xff0c;用于创建和编辑排版、图标、标志、插图和其他类型的矢量图形。 illustrator 2023 mac软件特点 矢量图形&#xff1a;illustrator创建的图形是矢量图形&#xff0c;可以无限放大而不失真&#xff0c;这与像素图形编辑软…

【接口测试】Jmeter接口实战-Dubbo接口+造10W数据测试(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、Windows环境通…