代码随想录算法训练营第三十八天 | Java |509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯【动态规划】

509. 斐波那契数

题目:斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1

给定 n ,请计算 F(n) 。

提示:

  • 0 <= n <= 30

思路:斐波那契数列当前元素为前两项元素之和,因此本题考虑n的大小,当n小于2时,直接返回n;当n大于2时,套用递推公式。本题主要练习动态规划解题五步曲:确定dp数组的定义、下标;递推公式;dp数组初始化‘遍历顺序;dp数组打印。

注意:数组空间大小初始化时注意n+1,斐波那契数列从f(0)开始

Java实现: 

class Solution {
    public int fib(int n) {
        // f(n)为数组前两位,即f(0)=0,f(1)=1
        if(n<1){
            return n;
        }
        // f(n) = f(n-1) + f(n-2)
        else{
            // 初始化数组空间大小
            int[] f = new int[n + 1];
            f[0] = 0;
            f[1] = 1;
            // 数组遍历起点下标
            for(int i=2;i<=n;i++){
                f[i] = f[i-1] + f[i-2];
            }
            return f[n];
        }
    }
}

70. 爬楼梯 

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

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

提示:

  • 1 <= n <= 45

思路:分解爬楼梯问题,第一个台阶有【1】1种方法;第二个台阶有【1+1,2】2种方法; 第三个台阶:从第二个台阶直接【+1】即2种方法上来,或者从第一个台阶【+2】即1种方法上来,因此共3种方法;第四个台阶:从第三个台阶直接【+1】即3种方法上来,或者从第二个台阶【+2】即2种方法,因此共5种方法,以此类推。因此本题实质上也是斐波那契数列。

注意:上台阶是递进的,每次可以选择上1阶或者2阶,因此上到当前台阶时有两种选择方案,注意理清这一过程。

Java实现

class Solution {
    public int climbStairs(int n) {
        if(n<3) {return n;}
        else{
            int dp[] = new int[n+1];
            dp[0] = 0; // 初始化为0,无实际意义
            dp[1] = 1;
            dp[2] = 2;
            for(int i=3;i<=n;i++){
                dp[i] = dp[i-1] + dp[i-2]; 
            }
            return dp[n];
        }
        
    }
}

3  746. 使用最小花费爬楼梯 

题目:给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。

你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。

请你计算并返回达到楼梯顶部的最低花费。

提示:

  • 2 <= cost.length <= 1000
  • 0 <= cost[i] <= 999

思路:本题首先要考虑清楚dp数组定义,dp[i] 为记录当前爬到第 i 台阶上所花费最小费用。根据题意,可以选择0或者1下标台阶开始起步,因此,起步不计费 ,即 dp[0],dp[1]都是0。下面是递推公式:每次可选择上1或2个台阶,因此到第 i 个台阶时,最小花费为min(dp[i-1]+cost[i-1],dp[i-2]+cost[d-2])。上台阶依次向后遍历即可。

注意:dp数组长度为cost.length+1,登顶花费为dp[cost.length]

Java实现

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int n = cost.length;
        int dp[] = new int[n+1];  // 到达当前台阶所花费最小的金额
        // 长度初始化为n+1,最后一个记录的是达到最终台阶所花费的金额
        dp[0] = 0;  // 初始上第一个和第二个台阶不花钱
        dp[1] = 0;
        for(int i=2;i<=n;i++){
            dp[i] = Math.min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
        }
        return dp[n];
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值