登台阶爬楼梯问题

登台阶爬楼梯问题

问题描述

有N个台阶,0<N<=50, 每次只跳1个或者3个台阶,输入N, 有多少种方式到达台阶终点

# 示例 1:
输入:n = 3
输出:2
解释:有两种方法可以爬到楼顶。
1.   1 阶 + 1 阶+1阶
2.   3阶

# 示例 2:
输入:n = 4
输出:3
解释:有两种方法可以爬到楼顶。
1.   1 阶 + 1 阶 + 1阶 +  1阶
2.   3阶 + 1阶
3.   1阶 + 3阶

很多时候我们自己对问题的描述所呈现的大都基于固有的思想,我们需要在固有的思想上怎么去优化这个问题才是重点。

-- 首先我们需要寻找规律 
台阶1   【1】   
台阶2   【11】
台阶3   【111,3】 
台阶4   【13 ,31 ,1111】       
台阶5   【113 ,311 ,131,111】        
台阶6   【1113,1131,1311,3111,111111,33】
台阶7   【11113 ,11131,11311,13111,31111,331,133,313,1111111】 

f(1) = 1 
f(2) = 1
f(3) = 2
f(4) = f(1) + f(3) = 3
f(5) = f(2) + f(4) = 4
f(6) = f(3) + f(5) = 6
f(7) = f(4) + f(6) = 9 
...
F(N) = F(N-3) + F(N-1)
其实很好理解:等台阶 只有两种:1 和 3  需要统计的是这两种的个数 也就是我们需要爬的总数。
第 n 级台阶的方案数是爬到第 n−1 级台阶的方案数和爬到第 n−3 级台阶的方案数的和.
递归
#普通递归  重复计算之前的树节点 时间复杂度 O(2^n)  空间复杂度(On)
#优化方法 在此基础上保存之前计算过的节点 使得时间复杂度(On)
def f1(n):
    if n==1:return 1
    elif n==2:return 1
    elif n==3:return 2
    else:
        res=f1(n-1)+f1(n-3)
        return res
        
[f1(i) for i in range(1,10)]
#[1, 1, 2, 3, 4, 6, 9, 13, 19]
#优化 存储之间计算的节点数据 如计算f(5)时  不必再次计算f(4)和f(2) 存储

 def f11(n):
        memo=[]
        if n == 0 or n == 1:
            return 1
        if memo[n] == -1:
            memo[n] = f11(n- 1, memo) + f11(n - 3, memo)
        return memo[n]
    # memo: [-1] * (n - 1)
    # -1 表示没有计算过,最大索引为 n,因此数组大小需要 n + 1
    return f11(n, [-1] * (n + 1))

动态规划

# 动态规划
def funa(n):
    if n<2:
        return 1
    if n>=2:
        dp = [0]*(n+1)
        dp[0] = 1
        dp[1] = 1
        dp[2] = 2
        for i in range(3,n+1):
            dp[i] = dp[i-1] + dp[i-3]
    return dp[n-1]
#空间复杂度O(n)  时间复杂度O(n)
[funa(i) for i in range(1,10)]
#[1, 1, 2, 3, 4, 6, 9, 13, 19]
滚动数组
#动态规划
def f3(n):
    if n==0:return 0#初始化前3项
    if n==1:return 1
    if n==2:return 1
    if n==3:return 2
    p,q,r=1,1,2
    # 从第4项开始遍历,由于n算在结果中,故range第二个数为n+1,区间为[3, n+1)
    for i in range(4,n+1):#节省空间  不使用数组
        p ,q, r = q , r ,(r+p)#每一项都是 前i-1  和 前 i-3  通过移动状态
    return r
# 时间复杂度:循环执行 nn 次,每次花费常数的时间代价,故渐进时间复杂度为 O(n)。
# 空间复杂度:这里只用了常数个变量作为辅助空间,故渐进空间复杂度为 O(1)。
[f3(i) for i in range(1,10)]
#[1, 1, 2, 3, 4, 6, 9, 13, 19]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Elvis_hui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值