Leetcode刷题记录

1.动态规划

总结: 解决动态规划问题最难的地方有两点:

如何定义 f(n)f(n)
如何通过 f(1)f(1), f(2)f(2), … f(n - 1)f(n−1) 推导出 f(n)f(n),即状态转移方程

1)线性动态规划

单串 dp[i] 线性动态规划最简单的一类问题,输入是一个串,状态一般定义为 dp[i] := 考虑[0..i]上,原问题的解,其中 i 位置的处理,根据不同的问题,主要有两种方式:

第一种是 i 位置必须取,此时状态可以进一步描述为 dp[i] := 考虑[0..i]上,且取 i,原问题的解;
第二种是 i 位置可以取可以不取
大部分的问题,对 i 位置的处理是第一种方式,例如力扣:

70 爬楼梯问题
801 使序列递增的最小交换次数
790 多米诺和托米诺平铺
746 使用最小花费爬楼梯
线性动态规划中单串 dp[i] 的问题,状态的推导方向以及推导公式如下

1. 依赖比 i 小的 O(1) 个子问题
dp[n] 只与常数个小规模子问题有关,状态的推导过程 dp[i] = f(dp[i - 1], dp[i - 2], ...)。时间复杂度 O(n)O(n),空间复杂度 O(n)O(n) 可以优化为 O(1)O(1),例如上面提到的 70, 801, 790, 746 都属于这类。

如图所示,虽然紫色部分的 dp[i-1], dp[i-2], ..., dp[0] 均已经计算过,但计算橙色的当前状态时,仅用到 dp[i-1],这属于比 i 小的 O(1)O(1) 个子问题。

2. 依赖比 i 小的 O(n) 个子问题
dp[n] 与此前的更小规模的所有子问题 dp[n - 1], dp[n - 2], ..., dp[1] 都可能有关系。

状态推导过程如下:


dp[i] = f(dp[i - 1], dp[i - 2], ..., dp[0])
依然如图所示,计算橙色的当前状态 dp[i] 时,紫色的此前计算过的状态 dp[i-1], ..., dp[0] 均有可能用到,在计算 dp[i] 时需要将它们遍历一遍完成计算。

其中 f 常见的有 max/min,可能还会对 i-1,i-2,...,0 有一些筛选条件,但推导 dp[n] 时依然是 O(n)O(n) 级的子问题数量。

以 min 函数为例,这种形式的问题的代码常见写法如下
for i = 1, ..., n
    for j = 1, ..., i-1
        dp[i] = min(dp[i], f(dp[j]))

2)前缀和

3)区间动态规划

4)背包动态规划

5)状态压缩动态规划

6)计数问题

7)矩阵快速幂

8)数位动态规划

2.递归

3.字符串

4.哈希表

5.二分查找

6.深度优先搜索

7.广度优先搜索

8.排序

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值