【每日算法】动态规划2(中等)

简介: 动态规划(中等)

16fb98eea012ef0cb446588ddc50662.png

题目

剑指 Offer 47. 礼物的最大价值

在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?

示例:

输入: 
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
输出: 12
解释: 路径 1→3→5→2→1 可以拿到最多价值的礼物
复制代码

分析

本题主要思路是利用动态规划将每个格子的最大值计算出来

需要注意的是对各种边界情况的处理

  • 定义 dp 数组

dp[i][j] 表示i行j列可取的最大值

  • 写出dp数组状态转移方程
dp[i][j] = max{dp[i-1][j], dp[i][j-1]} + grid[i][j]
  • 初始化dp数组
dp[0][0] = grid[0][0]

迭代求解 dp 数组

分析边界情况,先求出边界,在求出内部

  • 第一行的最大值只能由第一行遍历过去求得
  • 第一列的最大值只能由第一列遍历过去求得
  • 内部的按行或者按列逐层遍历得到即可
  • 返回结果

实现

function maxValue(grid: number[][]): number {
    let m = grid.length     // 行
    let n = grid[0].length  // 列
    let dp = new Array(m)
    for (let i = 0; i < dp.length; i ++) {
        dp[i] = new Array(n)
    }
    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 ++) {
            dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]) + grid[i][j]
        }
    }
    return dp[m-1][n-1]
};
复制代码

题目

剑指 Offer 46. 把数字翻译成字符串

给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。

示例:

输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
复制代码

分析

这道题分析到最后与青蛙跳台阶有点类似,只是在每一次求解时都需要格外判断一下是否可以跳

  • 定义 dp 数组

dp[i] 以第 i 个字母结尾有几种不同方法

  • 写出状态转移方程
  • dp[i] = dp[i-1] 当结尾两个字母相连无法解析成其它字母时
  • dp[i] = dp[i-1] + dp[i-2] 当结尾两个字母可以解析成其它字母时,说明最终结果可以由前两种状态得到
  • 初始化dp数组
dp[0] = 1
dp[1] = 判断是否满足连子翻译条件,是为2,否为1
  • 迭代求解 dp 数组

实现

function translateNum(num: number): number {
    // dp[i] 以第 i 个字母结尾有几种不同方法
    let str = num.toString()
    let len = str.length
    let dp = []
    dp[0] = 1
    let i = 1
    while(i < len) {
        let cur = + (str[i - 1] + str[i])
        if (cur >= 10 && cur <=25) {
            if ( i == 1) {
                dp[i] = 2
            } else {
                dp[i] = dp[i - 1] + dp[i - 2]
            }
        } else {
            dp[i] = dp[i - 1]
        }
        i ++
    }
    return dp[len - 1]
};
相关文章
|
1月前
|
存储 算法
深入了解动态规划算法
深入了解动态规划算法
51 1
|
1月前
|
算法 测试技术 C++
【动态规划算法】蓝桥杯填充问题(C/C++)
【动态规划算法】蓝桥杯填充问题(C/C++)
|
4月前
|
算法 开发者 Python
惊呆了!Python算法设计与分析,分治法、贪心、动态规划...这些你都会了吗?不会?那还不快来学!
【7月更文挑战第10天】探索编程巅峰,算法至关重要。Python以其易读性成为学习算法的首选。分治法,如归并排序,将大问题拆解;贪心算法,如找零问题,每步求局部最优;动态规划,如斐波那契数列,利用子问题解。通过示例代码,理解并掌握这些算法,提升编程技能,面对挑战更加从容。动手实践,体验算法的神奇力量吧!
72 8
|
4月前
|
算法 Python
算法不再难!Python分治法、贪心、动态规划实战解析,轻松应对各种算法挑战!
【7月更文挑战第8天】掌握Python算法三剑客:分治、贪心、动态规划。分治如归并排序,将大问题拆解递归解决;贪心策略在每步选最优解,如高效找零;动态规划利用子问题解,避免重复计算,解决最长公共子序列问题。实例展示,助你轻松驾驭算法!**
67 3
|
25天前
|
算法
动态规划算法学习三:0-1背包问题
这篇文章是关于0-1背包问题的动态规划算法详解,包括问题描述、解决步骤、最优子结构性质、状态表示和递推方程、算法设计与分析、计算最优值、算法实现以及对算法缺点的思考。
55 2
动态规划算法学习三:0-1背包问题
|
25天前
|
算法
动态规划算法学习四:最大上升子序列问题(LIS:Longest Increasing Subsequence)
这篇文章介绍了动态规划算法中解决最大上升子序列问题(LIS)的方法,包括问题的描述、动态规划的步骤、状态表示、递推方程、计算最优值以及优化方法,如非动态规划的二分法。
58 0
动态规划算法学习四:最大上升子序列问题(LIS:Longest Increasing Subsequence)
|
25天前
|
算法
动态规划算法学习二:最长公共子序列
这篇文章介绍了如何使用动态规划算法解决最长公共子序列(LCS)问题,包括问题描述、最优子结构性质、状态表示、状态递归方程、计算最优值的方法,以及具体的代码实现。
103 0
动态规划算法学习二:最长公共子序列
|
1月前
|
存储 人工智能 算法
【算法——动态规划】蓝桥ALGO-1007 印章(C/C++)
【算法——动态规划】蓝桥ALGO-1007 印章(C/C++)
【算法——动态规划】蓝桥ALGO-1007 印章(C/C++)
|
25天前
|
存储 算法
动态规划算法学习一:DP的重要知识点、矩阵连乘算法
这篇文章是关于动态规划算法中矩阵连乘问题的详解,包括问题描述、最优子结构、重叠子问题、递归方法、备忘录方法和动态规划算法设计的步骤。
90 0
|
1月前
|
算法 C++
【算法解题思想】动态规划+深度优先搜索(C/C++)
【算法解题思想】动态规划+深度优先搜索(C/C++)