一天一大 leet(最小路径和)难度:中等-Day20200723
时间:2022-07-25
本文章向大家介绍一天一大 leet(最小路径和)难度:中等-Day20200723,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目:
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:
每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
回归之前的逻辑答题就两种方式解决:动态规划、递归
动态规划
思路
- 记录到达每一格时最小的路径
- 到记录到 dp[m][n]时就是需要的结果
- 到达每一格的路径和可能有两种
- 从上面单元格进入则:dp[i][j] = dp[i][j-1]+grid[i][j]
- 从上面单元格进入则:dp[i][j] = dp[i-1][j]+grid[i][j]
- 索引存在-1 则需要注意边界问题:
- grid 长 0,返回 0
- dp[0][0] = grid[0][0]
- 遍历从 i=1,j=1 开始
- dp[i][0],dp[0][j],使用当前行或者列累加做默认值
1 |
2 |
3 |
---|---|---|
1 |
2 |
↓ |
2 |
-> |
dp[i][j] |
3 |
… |
… |
/**
* @param {number[][]} grid
* @return {number}
*/
var minPathSum = function (grid) {
let m = grid.length,
n = grid[0] ? grid[0].length : 0
if (m === 0 || n === 0) return 0
let dp = Array.from({ length: m }, () => new Array(n).fill(Number.MAX_VALUE))
// 起点
dp[0][0] = grid[0][0]
// 补齐首行路径和
for (let i = 1; i < m; i++) {
dp[i][0] = dp[i - 1][0] + grid[i][0]
}
// 补齐首列路径和
for (let j = 1; j < n; j++) {
dp[0][j] = dp[0][j - 1] + grid[0][j]
}
for (let i = 1; i < m; i++) {
for (let j = 1; j < n; j++) {
// 从路径和较小的地方进入
let itemMin = Math.min(dp[i - 1][j], dp[i][j - 1])
dp[i][j] = Math.min(itemMin + grid[i][j], dp[i][j])
}
}
return dp[m - 1][n - 1]
}
降维
- dp 降维不记录到每个单元格的最小路径
- dp 记录到达每行的最小路径
d[0] |
← |
d[i] |
---|---|---|
1 |
2 |
↑ |
2 |
3 |
↑ |
3 |
... |
grid[i][j] |
- 行路径放置到 dp[0]
- 列路径放置到 dp[j]
/**
* @param {number[][]} grid
* @return {number}
*/
var minPathSum = function (grid) {
let m = grid.length,
n = grid[0] ? grid[0].length : 0
if (m === 0 || n === 0) return 0
let dp = new Array(n).fill(0)
dp[0] = grid[0][0]
// 补齐首列路径和
for (let i = 1; i < n; i++) {
dp[i] = dp[i - 1] + grid[0][i]
}
for (let i = 1; i < m; i++) {
// 开始每列循环时限初始化本列起点路径和,到达本列前的路径和
dp[0] = dp[0] + grid[i][0]
for (let j = 1; j < n; j++) {
dp[j] = Math.min(dp[j - 1], dp[j]) + grid[i][j]
}
}
return dp[n - 1]
}
递归
- 计算路径的逻辑还是和上面一样,入口+当前单元格中的值
- 递归参数,行列(i,j)
- 递归边界条件:
- i 和 j 任意指针越界说明指针并为指向单元格丢弃该值,使用最大值在取 min 时会自行丢弃
- dp 存储过此单元格路径和直接返回存储在 dp 中的值
/**
* @param {number[][]} grid
* @return {number}
*/
var minPathSum = function (grid) {
let m = grid.length,
n = grid[0] ? grid[0].length : 0
if (m === 0 || n === 0) return 0
let dp = Array.from({ length: m }, () => Array(n).fill(0))
// 起点
dp[0][0] = grid[0][0]
function get_sum(i, j) {
if (i < 0 || j < 0) return Number.MAX_VALUE
if (dp[i][j]) return dp[i][j]
let itemMin = grid[i][j] + Math.min(get_sum(i - 1, j), get_sum(i, j - 1))
dp[i][j] = itemMin
return itemMin
}
return get_sum(m - 1, n - 1)
}
可以看到有一个用例没有通过,可以借助降维的思路,对存储的 dp 降维
/**
* @param {number[][]} grid
* @return {number}
*/
var minPathSum = function (grid) {
let m = grid.length,
n = grid[0] ? grid[0].length : 0
if (m === 0 || n === 0) return 0
let dp = new Map()
// 起点
dp.set('0-0', grid[0][0])
function get_sum(i, j) {
if (i < 0 || j < 0) return Number.MAX_VALUE
if (dp.has(i + '-' + j)) return dp.get(i + '-' + j)
let itemMin = grid[i][j] + Math.min(get_sum(i - 1, j), get_sum(i, j - 1))
dp.set(i + '-' + j, itemMin)
return itemMin
}
return get_sum(m - 1, n - 1)
}
- Python数据增强(data augmentation)库--Augmentor 使用介绍
- Leetcode-Easy 101. Symmetric Tree
- 数据结构-栈的定义及python实现
- 【关关的刷题日记59】Leetcode 257 Binary Tree Paths
- 学大伟业 国庆Day2
- ECMAScript 6入门 - 变量的解构赋值
- 二叉排序树 python实现
- ES6新特性概览
- 数据结构-顺序表的定义及python实现
- 洛谷P1516 青蛙的约会
- python实现二叉树的创建和遍历
- python中numpy模块下的np.clip()的用法
- Leetcode-Easy 543. Diameter of Binary Tree
- Leetcode-Easy 572. Subtree of Another Tree
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- MinGW 安装
- 实践 | 目前最快精度最高检测框架(EfficientDet)
- 解决拉取github仓库报错“gnutls_handshake() failed”问题
- HTML 学习
- Go 语言学习之数组
- 坐姿不对,屏幕就变模糊!小姐姐教你用TensorFlow做一款“隐形背背佳”
- 七日Python之路--第九天(blog与Django)
- Python数据可视化-seaborn Iris鸢尾花数据
- pythonGUI -- pyside安装与初试
- TS 设计模式02 - 建造者模式
- 艺术鬼才!Unicode 字符还能这么玩?
- TS 设计模式03 - 单例模式
- MySQL 案例:Limit 分页查询优化
- 白话Xavier | 神经网络初始化的工程选择
- matplotlib 设置绘图时显示中文