动态规划

菲波那切数列

L70 爬楼梯

easy 过。 子问题不是独立的,还包含了子子问题。

L198 大家劫舍()

描述问题的最优子结构(一个问题的最优解包含了子问题的一个最优解),递归定义最优解的值。

最优子结构性质是能应用动态规划的标志之一。

注: easy 过

L213 打家劫舍 II(☆☆)

也称环形抢劫,首先考虑减小问题的规模,后面发现可以转化为L198. 分别对区间0n-2 和 1n-1用L198的代码,最大值即为所求。

2021-1-10 : 要用到组合的思路,分类去列情况。不要光想。

L337. 打家劫舍 III(☆☆☆☆)

树形dp问题. 用到了后序遍历

f(o)表示选择o结点情况下,所得到的最大和,g(o)表示不选择o结点情况下,所得到的最大和

☆//每个结点有3次访问机会,用后序遍历可以将递归转化为非递归

☆树形dp问题这里的表用的是hashmap

2021-1-10 22:06:22

g = max {f(l), f(l)} + max{f(r),g(r)}

为什么要用hash?

  • 映射,键值对。存储节点的f g值 ,所以用2个hashmap.

为什么要用后序?

  • 用后序递归就可以

  • 因为递归是从上到下,动态规划要自底向上,而最后遍历到根的正是后序。

  • 问题的规模很小达到可解时。

    • f
      • 最后肯定能遍历到叶子节点,叶子节点的f就是自身的val
      • 非叶子节点的f,g(l) + g(r)
    • g
      • 叶子节点的g就是0 , 用getOrDefault,从hashmap中取 默认是0.,因为非递归会从最底节点开始。

矩阵路径

L416 分割等和子集

累加和问题,这题递归方法超时。

2020-09-22 23:15:18当前的动态规划解法有待进一步超时

动态规划步骤:

考虑减小问题的规模

尝试写出递推式=>写出递归的解法

用空间换时间,转为动态规划。

L53 最大子序和

这题关键在于定义最优解,用 f(i) 代表以第 i个数结尾的「连续子数组的最大和」,找出最大的。 a(i) 表示数字第i个元素,要判断是否要加入前面的子序和。前面的大于0才加。

L121121. 买卖股票的最佳时机

f(i)定义为数组前i个数的解,就是第i天的解,可能为负数,不是最优解。也就是找出每天的解,用1个max变量来记录最优解. 第i天的解第i天 - 前面最小的。

这个解法在暴力解(问题的所有子问题) 和纯动态规划之间.

序列

L300. 最长递增子序列(☆☆☆☆)

  • 关键在于定义f(n) :以n结尾的最长递增子序列的长度 , f(n-1)就是以第n-1个数结尾的最长递增子序列的长度。前面的每个f(i) i,从 0到N-1 , 于第n个数比较,
  • 下一步减小问题规模没错,f(n) 于f(n-1)比较
  • 然后自底向上

子串,子数组一定连续,子序列不一定连续。

L376 摆动序列

  • 有和最长递增子序列类似的地方,这题要求正负交替的子序列
  • 第一个差可能是正可能是负 这点没注意到 , 因此我的解法分了2种情况

L646最长数对链

  • 数对的第一个数是无序,因此我先写了选择排序
  • f[i] 表示以第i个数对结尾的 最长数对链的长度

L1143 最长公共子序列

重要的写出的递归式。 找f(n) 和f(n-1)的关系,这里是先假设x和y的最后一个字母是否相同,反过来考虑,也是从上到下,很关键。

  • 定义要的那个表的d[i][j]的定义 很重要

累加和问题:

  • L416
  • 累加和等于target(2^n^种)

数组区间

L303 过

背包问题

416. 分割等和子集

*** 再做不会做了,挺有难度。

什么叫多项式时间复杂度?

动态规划解法:

题目可以转换为能否找到几个数的和等于数组和的一半target。

传统的「0-10−1 背包问题」要求选取的物品的重量之和不能超过背包的总容量。

异常情况:

0.n < 2 不能被划分

1.和为奇数->false

2.最大的数比target大,那么除了最大的数的其他数的和小于target

关键是定义dp[i][j] 表示在范围[0,i]内能否找个几个数的和等于j ,分为j >= nums[i] 和 j < nums[i]。

i从[0,n-1] , j从 0 ,target.

1.j >= nums[i]

  • dp[i][j] = dp[i-1][j] | dp[i - 1][j - nums[i]];
    • 分为选Nums[i] 和不选的情况 只要满足其一就行

2.j < nums[i]

  • dp[i][j] = dp[i-1][j] 不能选

322. 零钱兑换

花了蛮长时间。 没定义好dp数组,他就是一维的。 没找到递推关系。

f[amout] = f[amout - c] + 1 . 思维一直在 二维dp

518. 零钱兑换 II

在LeetCode上有两道题目非常类似,分别是

  • 70.爬楼梯

  • 518.零钱兑换 II

如果我们把每次可走步数/零钱面额限制为[1,2], 把楼梯高度/总金额限制为3. 那么这两道题目就可以抽象成”给定[1,2], 求组合成3的组合数和排列数”。

494 改变一组数的正负号使得它们的和为一给定数

目标和

背包问题,范围是在-1000,1000.

关键在定义dp[i][j]的含义 以及它的表示。

474 01 字符构成最多的字符串

这个太难。

2


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!