1.16 LeetCode总结(基本算法)动态规划2

本文介绍了递归求解爬楼梯问题中的重复计算问题,通过引入备忘录和动态规划的方法降低时间复杂度,对比了自顶向下和自底向上的解法,以及以0-1背包问题为例展示了动态规划的应用过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


70. 爬楼梯

在这里插入图片描述
首先想到的是递归:

// 递归
int climbStairs(int n) {
   
   

	if (n == 1) {
   
   
		return 1;
	} else if (n == 2) {
   
   
		return 2;
	}

	return climbStairs(n - 1) + climbStairs(n - 2);
}

在这里插入图片描述
我们先来看看这个递归的时间复杂度吧:

递归时间复杂度 = 解决一个子问题时间*子问题个数
一个子问题时间 = f(n-1)+ f(n-2),也就是一个加法的操作,所以复杂度是 O(1);
问题个数 = 递归树节点的总数,递归树的总节点 = 2n-1,所以是复杂度O(2n)。
因此,青蛙跳阶,递归解法的时间复杂度 = O(1) * O(2^n) = O(2^n),就是指数级别的,爆炸增长的,如果n比较大的话,超时很正常的了。

回过头来,你仔细观察这颗递归树,你会发现存在大量重复计算,比如 f(8) 被计算了两次,f(7) 被重复计算了3次…所以这个递归算法低效的原因,就是存在大量的重复计算!

既然存在大量重复计算,那么我们可以先把计算好的答案存下来,即造一个备忘录,等到下次需要的话,先去备忘录查一下,如果有,就直接取就好了,备忘录没有才开始计算,那就可以省去重新重复计算的耗时啦!这就是带备忘录的解法。

自底向上的动态规划
动态规划跟带备忘录的递归解法基本思想是一致的,都是减少重复计算,时间复杂度也都是差不多。但是呢:

带备忘录的递归,是从f(10)往f(1)方向延伸求解的,所以也称为自顶向下的解法。
动态规划从较小问题的解,由交叠性质,逐步决策出较大问题的解,它是从f(1)往f(10)方向,往上推求解,所以称为自底向上的解法。
动态规划有几个典型特征,最优子结构、状态转移方程、边界、重叠子问题。在青蛙跳阶问题中:

f(n-1) 和 f(n-2) 称为 f(n) 的最优子结构
f(n) = f(n-1) + f(n-2) 就称为状态转移方程
f(1) = 1, f(2) = 2 就是边界啦
比如f(10)= f(9)+f(8), f(9) = f(8) + f(7) , f(8)就是重叠子问题。
我们来看下自底向上的解法,从 f(1) 往 f(10) 方向,想想是不是直接一个for循环就可以解决啦,如下:
在这里插入图片描述

int climbStairs(int n){
   
   
    //f(x) = f(x-1) + f(x-2) 
    if (n <= 1){
   
    // 第0阶和第1阶只有一种方法
        return 1;
    }
    int way;
    int memo[2] = {
   
   1,1};
    for (int i 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值