swift算法:爬楼梯

1、描述

假设你正在爬楼梯,需要n阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定n是一个正整数。

例1:输入:2

          输出:2

          解释:有两种方法可以爬到楼顶

                      1)1 阶 + 1 阶

                      2)2 阶

例2:输入:3

          输出:3

          解释:有三种方法可以爬到楼顶

                      1)1 阶 + 1 阶 + 1 阶

                      2)1 阶 + 2 阶

                      3)2 阶 + 1 阶

 

2、算法

解法一:暴力法

思想:我们将会把所有可能爬的阶数进行组合,也就是 1 和 2 。而在每一步中我们都会继续调用climbStairs 这个函数模拟爬2 阶的情形,并返回两个函数的返回值之和。

         climbStairs(i,n)=(i+1,n)+climbStairs(i+2,n)

         其中 i 定义了当前阶数,而n 定义了目标阶数。

时间复杂度:O(2^n)

func climbStairs(_ n: Int) -> Int {
        return climb_Stairs(0, n)
    }
    func climb_Stairs(_ i : Int, _ n : Int)-> Int{
        if i > n {
            return 0
        }
        if i == n {
            return 1
        }
        return climb_Stairs(i+1, n)+climb_Stairs(i+2, n)
    }

 

解法二:记忆化递归

思路:在暴力法中,我们计算每一步的结果时出现了冗余。另一种思路是,我们可以把每一步的结果存储在memo 数组之中,每当函数再次被调用,我们就直接从memo 数组返回结果。 在memo 数组的帮助下,我们得到了一个修复的递归树,其大小减少到n。

时间复杂度:O(n)

func climbStairs(_ n: Int) -> Int {
        var memo : [Int] = [Int].init(repeating: 0, count: n+1)
        return climb_Stairs1(0, n, &memo)
    }
 func climb_Stairs1(_ i : Int, _ n : Int, _ memo : inout [Int])-> Int{
        if i > n {
            return 0
        }
        if i == n {
            return 1
        }
        if memo[i] > 0 {
            return memo[i]
        }
        memo[i] = climb_Stairs1(i+1, n, &memo)+climb_Stairs1(i+2, n, &memo)
        return memo[i]
    }

 

解法三:动态规划

思想:

它的最优解可以从其子问题的最优解来有效的构建

第i阶可以由以下两种方法得到:

            1)在第(i-1)阶后向上爬1阶

            2)在第(i-2)阶后向上爬2阶

所以到达第i阶的方法总数就是到第(i-1)阶和第(i-2)阶的方法数之和

令dp[i]表示能到达第i阶的方法总数:dp[i] = dp[i-1]+dp[i-2]

时间复杂度:O(n)

func climbStairs(_ n: Int) -> Int {
        if n==1 {
            return 1
        }
        
        var dp : [Int] = [Int].init(repeating: 0, count: n+1)
        dp[1] = 1
        dp[2] = 2
        var i = 3
        while i<=n {
            dp[i] = dp[i-1]+dp[i-2]
            i += 1
        }
        return dp[n]
    }

 

解法四:斐波那契数

思路:由动态规划式子dp[i] = dp[i-1]+dp[i-2]分析,可以很容易的得出dp[i]就是第i个斐波那契数

            Fib(n) = Fib(n-1) + Fib(n-2)

           我们必须以找出以1和2作为第一项和第二项的斐波那契数列中的第n个数,也就是说Fib(1) = 1,Fib(2) = 2

时间复杂度:O(n)

func climbStairs(_ n: Int) -> Int {
        if n==1 {
            return 1
        }
        
        var first = 1
        var second = 2
        var i = 3
        while i<=n {
            var third = first+second
            first = second
            second = third
            
            i += 1
        }
        return second
    }
    

 

解法五:斐波那契数列

思想:

时间复杂度:O(logn)

func climbStairs(_ n: Int) -> Int {
        let sqrt5 : Double = sqrt(5)
        let fibn : Double = pow((1+sqrt5)/2, Double(n+1))-pow((1-sqrt5)/2, Double(n+1))
        return Int(fibn/sqrt5)
    }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值