LeetCode 62,从动态规划想到更好的解法
本文始发于个人公众号:TechFlow,原创不易,求个关注
今天是LeetCode专题第36篇文章,我们一起来看下LeetCode的62题,Unique Paths。
题意
其实这是一道老掉牙的题目了,我在高中信息竞赛的选拔考试上就见过这题。可想而知它有多古老,或者说多经典吧。一般来说能够流传几十年的算法题,一定是经典中的经典。下面我们就来看下它的题意。
这题的题意很简单,给定一个矩形的迷宫,左上角有一个机器人,右下角是目的地。这个机器人只能向下走或者是向右走,请问这个机器人走到目的地的路径一共有多少种?
这题很良心地给定了条件,矩形的长和宽都不超过100.
样例
Input: m = 3, n = 2
Output: 3
Explanation:
From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:
1. Right -> Right -> Down
2. Right -> Down -> Right
3. Down -> Right -> Right
Input: m = 7, n = 3
Output: 28
解法
在我写题解的时候,我突然想起来上一次见到它好像是在某个综艺节目当中。它被作为一道智力题来考一些明星嘉宾,好像一众明星里面,只有关晓彤做了出来。。。
它作为智力题有一个标准的模板式解法:
对于图中的C点来说,从起点通往它的路径数量等于通往A点和B点路径的和。
这个结论我们很多人都知道,因为C点只有两个来源,一个是A点一个是B点。它既可以从A点来,也可以从B点来,所以应该是一个加和的关系。
这当然是没错的,但不知道大家从这个过程当中有没有什么感悟。C点的上游是A点和B点,也就是说C状态是由A状态或者是B状态转移到的。这不就是一个动态规划算法吗?
我们用dp记录每一个位置的答案的话,那么可以很轻松地写出状态转移方程:
dp[i][j] = dp[i-1][j] + dp[i][j-1]
我们用代码把这个方程实现就能解出问题了。
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
dp = [[0 for _ in range(n+2)] for _ in range(m+2)]
dp[0][1] = 1
for i in range(1, m+1):
# 特殊处理第一列,因为第一列只有1种
dp[i][1] = dp[i-1][1]
for j in range(2, n+1):
dp[i][j] = dp[i-1][j] + dp[i][j-1]
return dp[m][n]
one more solution
如果只有上面这一种解法,那么这道题完全没有说的必要,也太简单了。这道题还有另外一种解法,会更加简单。
在上面的解法当中,我们是把这个问题当成了算法题来解决的,使用动态规划算法进行建模,适配题目来解决它。但如果我们换个思路,完全可以把它当做数学问题来解。
我们来分析一下问题,机器人要从左上角走到右下角,地图是没有缺陷的,所有点都可以到达。由于机器人没办法走回头路,也就是说机器人在通往终点的过程当中走过的路程是确定的。也就是要走n-1条横边和m-1条竖边。
边的总数和种类都确定了,其实这个问题可以转化一下。我们把走的横边看成是白球,走的竖边看成是黑球,那么这道题其实就可以转化成,我们有n-1个白球,m-1个黑球,现在把它们排成一排,一共有多少种方法?
这个是小学的组合数学问题,我们要从整体的n+m-2个物体当中,选出n-1个,那么显然答案就是:
不过,虽然我们用一个式子就表达了,但是要求解这个组合数,还是需要通过循环的。我们把它转化成:
接着我们用循环求解即可。
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
ret = 1
for i in range(1, n):
ret = ret * (n+m-1-i) // i
return ret
相比于上面的做法更加简短,虽然两者看起来都是的算法,好像差别不大。但是每个数的阶乘和组合数都是可以预处理的,在频繁求解的场景下,显然要比动态规划算法更快。
结尾
这道题就算是讲完了,大家会发现LeetCode过了50题之后,涉及到新的算法明显变少了。毕竟LeetCode并不是高强度的算法平台,主打的还是算法入门。这也限制了它的难度无法和codeforces、topcoder这种主打算法竞赛的平台相比。所以很多人刷到一百题左右的时候,就会觉得没意思。
感觉很多题目大同小异,新鲜感和正反馈都变少了。这个时候就需要我们把问题做精,多去思考和求解最完美的解法。即使是为了应付面试而刷题,这也是很有必要的。高水平的面试官往往都不会出LeetCode上的原题,都会加一些变化来考察选手,甚至有些大牛会出原创题。光摸清套路是不够的,我们还需要更加深入的理解。
套用一句电影台词作为结尾:we need to go deeper.
今天的文章就到这里,看官大人,请关注我吧
LeetCode 62,从动态规划想到更好的解法的更多相关文章
- LeetCode总结 -- 一维动态规划篇
这篇文章的主题是动态规划, 主要介绍LeetCode中一维动态规划的题目, 列表如下: Climbing StairsDecode WaysUnique Binary Search TreesMaxi ...
- [LeetCode] 72. 编辑距离 ☆☆☆☆☆(动态规划)
https://leetcode-cn.com/problems/edit-distance/solution/bian-ji-ju-chi-mian-shi-ti-xiang-jie-by-labu ...
- Effective Java 第三版——62. 当有其他更合适的类型时就不用字符串
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- LeetCode初级算法--动态规划01:爬楼梯
LeetCode初级算法--动态规划01:爬楼梯 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net ...
- MySQL root密码忘记,原来还有更优雅的解法!
一直以来,对于MySQL root密码的忘记,以为只有一种解法-skip-grant-tables. 问了下群里的大咖,第一反应也是skip-grant-tables.通过搜索引擎简单搜索了下,无论是 ...
- [Leetcode 62]机器人走路Unique Path 动态规划
[题目] A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below) ...
- [LeetCode] 62. 不同路径 ☆☆☆(动态规划)
动态规划该如何优化 描述 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” ). 机器人每次只能向下或者向右移动一步.机器人试图达到网格的右下角(在下图中标记为“Fi ...
- LeetCode 32,并不Hard的难题,解法超级经典,带你领略动态规划的精彩
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天给大家分享的是LeetCode当中的32题,这是一道Hard难度的题.也是一道经典的字符串处理问题,在接下来的文章当中,我们会详细地解读 ...
- 【LeetCode题解】动态规划:从新手到专家(一)
文章标题借用了Hawstein的译文<动态规划:从新手到专家>. 1. 概述 动态规划( Dynamic Programming, DP)是最优化问题的一种解决方法,本质上状态空间的状态转 ...
随机推荐
- Problem C Careful Ascent
数学问题. 在不经过shield时,竖直速度是1.所以时间就是y/1=y,,,,在经过shield时,时间为shield的数值长度*影响因素,然后总时间把他们加起来,最后再用水平方向的长度除以总时间, ...
- linux常用命令--文件的权限
ls -lh 显示权限 ls /tmp | pr -T5 -W$COLUMNS 将终端划分成5栏显示 chmod ugo+rwx directory1 设置目录的所有人(u).群组(g)以及其他人(o ...
- Asp.Net Core 3.0 学习3、Web Api 文件上传 Ajax请求以及跨域问题
1.创建Api项目 我用的是VS2019 Core3.1 .打开Vs2019 创建Asp.Net Core Web应用程序命名CoreWebApi 创建选择API 在Controller文件夹下面添加 ...
- 泛微ecology OA系统在数据库配置信息泄露
漏洞描述 攻击者可通过该漏洞页面直接获取到数据库配置信息,攻击者可通过访问存在漏洞的页面并解密从而获取数据库配置信息,如攻击者可直接访问数据库,则可直接获取用户数据,由于泛微e-cology默认数据库 ...
- 从零开始的计算机网络基础(图文并茂,1.8w字,面试复习必备)
前言 在互联网高速发展的今天,我们通过手机,电脑等通讯设备可以很轻松达到未出茅庐便知天下事的境界.每天我们都要访问数不胜数的网站,通过打开浏览器,输入网址两步搞定.当然更为常规的做法是打开浏览器,设置 ...
- 【JAVA基础】07 面向对象2
1. 代码块的概述和分类 面试的时候会问,开发不用或者很少用 代码块概述 在Java中,使用 {} 括起来的代码被称为代码块. 代码块分类 根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态 ...
- 15.Why lambda forms in python does not have statements?
Why lambda forms in python does not have statements? A lambda form in python does not have statement ...
- nodejs实现定时爬取微博热搜
The summer is coming " 我知道,那些夏天,就像青春一样回不来. - 宋冬野 青春是回不来了,倒是要准备渡过在西安的第三个夏天了. 废话 我发现,自己对 coding 这 ...
- MyBatis配置项--配置环境(environments)--数据源(dataSource)
数据源(dataSource) dataSource元素使用标准的JDBC数据源接口来配置JDBC连接对象的资源. ·许多MyBatis的应用程序会按示例中的例子来配置数据源.虽然是可选的,但为了使用 ...
- Express 文档(常见问题)
常见问题 我该如何构建我的应用程序? 这个问题没有明确的答案,答案取决于你的应用程序规模和所涉及的团队,为了尽可能灵活,Express在结构方面没有做出任何假设. 在你喜欢的任何目录结构中,路由和其他 ...