🤵♂️ 个人主页:@rain雨雨编程
😄微信公众号:rain雨雨编程
✍🏻作者简介:持续分享机器学习,爬虫,数据分析
🐋 希望大家多多支持,我们一起进步!
如果文章对你有帮助的话,
欢迎评论 💬点赞👍🏻 收藏 📂加关注+
目录
力扣 | 难度 |
---|---|
509. 斐波那契数 | 🟢 |
70. 爬楼梯 | 🟢 |
746. 使用最小花费爬楼梯 | 🟢 |
509. 斐波那契数
题目描述
斐波那契数列是一个经典的数列,其中每一项都是前两项的和。数列的前两项分别是0和1,即F(0) = 0和F(1) = 1。对于任意的n > 1,第n项F(n)可以通过F(n-1) + F(n-2)计算得出。本题要求给定一个整数n,计算出第n项斐波那契数F(n)。
示例 1:
输入:n = 2 输出:1 解释:F(2) = F(1) + F(0) = 1 + 0 = 1
示例 2:
输入:n = 3 输出:2 解释:F(3) = F(2) + F(1) = 1 + 1 = 2
思路步骤
-
基本情况判断:如果n小于等于1,直接返回n,因为F(0) = 0和F(1) = 1。
-
动态规划数组初始化:创建一个长度为n+1的数组dp,用于存储斐波那契数列的值。dp[0]初始化为0,dp[1]初始化为1。
-
循环计算:从第2项开始,使用循环计算每一项的值,即dp[i] = dp[i-1] + dp[i-2]。
-
返回结果:循环结束后,返回dp[n]作为结果。
代码实现
class Solution {
public int fib(int n) {
// 基本情况判断
if(n <= 1) return n;
// 动态规划数组初始化
int[] dp = new int[n + 1];
dp[0] = 0; // F(0) = 0
dp[1] = 1; // F(1) = 1
// 循环计算斐波那契数列的值
for(int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2]; // F(i) = F(i-1) + F(i-2)
}
// 返回第n项的值
return dp[n];
}
}
时间复杂度
时间复杂度为O(n)。这是因为我们需要从第2项开始,一直计算到第n项,每一项的计算时间是常数级别的,所以总的时间复杂度是线性的。
空间复杂度
空间复杂度为O(n)。这是因为我们使用了一个长度为n+1的数组来存储斐波那契数列的值。如果n很大,这个数组会占用相当大的内存空间。
70. 爬楼梯
题目描述
本题要求计算爬楼梯的不同方法数。假设有n阶楼梯,每次可以爬1阶或2阶,求到达楼顶的不同方法数。
示例 1:
输入:n = 2 输出:2 解释:有两种方法可以爬到楼顶。
-
1 阶 + 1 阶
-
2 阶
示例 2:
输入:n = 3 输出:3 解释:有三种方法可以爬到楼顶。
-
1 阶 + 1 阶 + 1 阶
-
1 阶 + 2 阶
-
2 阶 + 1 阶
思路步骤
-
基本情况处理:对于n=0和n=1的情况,直接返回1,因为只有一种方法爬到楼顶。
-
动态规划数组初始化:创建一个长度为n+1的数组dp,用于存储爬到每一阶楼梯的方法数。dp[0]和dp[1]都初始化为1,因为到达第一阶和第二阶都只有一种方法。
-
循环计算:从第2阶开始,使用循环计算每一阶的方法数,即dp[i] = dp[i-1] + dp[i-2]。这是因为到达第i阶的方法可以从第i-1阶走一步上来,或者从第i-2阶走两步上来。
-
返回结果:循环结束后,返回dp[n]作为结果,即到达第n阶的方法数。
代码实现
class Solution {
public int climbStairs(int n) {
// 基本情况处理
if (n <= 1) return 1;
// 动态规划数组初始化
int[] dp = new int[n + 1];
dp[0] = 1; // 到达第0阶的方法数为1
dp[1] = 1; // 到达第1阶的方法数为1
// 循环计算每一阶的方法数
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2]; // 到达第i阶的方法数是第i-1阶和第i-2阶方法数之和
}
// 返回到达第n阶的方法数
return dp[n];
}
}
时间复杂度
时间复杂度为O(n)。这是因为我们需要从第2阶开始,一直计算到第n阶,每阶的计算时间是常数级别的,所以总的时间复杂度是线性的。
空间复杂度
空间复杂度为O(n)。这是因为我们使用了一个长度为n+1的数组来存储每一阶的方法数。如果n很大,这个数组会占用相当大的内存空间。
优化空间复杂度
实际上,我们并不需要存储所有的中间结果,只需要存储最后两阶的结果即可,因此可以进一步优化空间复杂度。
优化后的代码实现
class Solution {
public int climbStairs(int n) {
// 基本情况处理
if (n <= 1) return 1;
// 只需要存储最后两阶的结果
int prev2 = 1; // 到达第1阶的方法数
int prev1 = 1; // 到达第2阶的方法数
int current = 0; // 当前阶的方法数
// 循环计算每一阶的方法数
for (int i = 3; i <= n; i++) {
current = prev1 + prev2; // 到达第i阶的方法数是第i-1阶和第i-2阶方法数之和
prev2 = prev1; // 更新第i-2阶的方法数
prev1 = current; // 更新第i-1阶的方法数
}
// 返回到达第n阶的方法数
return current;
}
}
优化后的空间复杂度
优化后的空间复杂度为O(1)。这是因为我们只存储了最后两阶的结果,不依赖于n的大小,所以空间复杂度是常数级别的。
746. 使用最小花费爬楼梯
题目描述
给定一个整数数组cost
,其中cost[i]
表示从第i
个台阶向上爬一个台阶或两个台阶的费用。可以选择从下标为0或1的台阶开始爬楼梯。目标是计算并返回到达楼梯顶部的最低花费。
示例 1:
输入:cost = [10,15,20] 输出:15 解释:你将从下标为 1 的台阶开始。
-
支付 15 ,向上爬两个台阶,到达楼梯顶部。 总花费为 15 。
示例 2:
输入:cost = [1,100,1,1,1,100,1,1,100,1] 输出:6 解释:你将从下标为 0 的台阶开始。
-
支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
-
支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
-
支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
-
支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
-
支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
-
支付 1 ,向上爬一个台阶,到达楼梯顶部。 总花费为 6 。
思路步骤
-
初始化动态规划数组:创建一个长度为
cost.length + 1
的数组dp
,用于存储到达每个台阶的最低花费。 -
边界条件:
dp[0]
和dp[1]
都初始化为0,因为从地面或第一个台阶开始爬不需要花费。 -
动态规划转移方程:从第2个台阶开始,使用循环计算每个台阶的最低花费。
dp[i]
的值是dp[i-1] + cost[i-1]
(从上一个台阶爬一个台阶上来的费用)和dp[i-2] + cost[i-2]
(从上上一个台阶爬两个台阶上来的费用)中的最小值。 -
返回结果:循环结束后,返回
dp[length]
作为结果,即到达楼梯顶部的最低花费。
代码实现
class Solution {
public int minCostClimbingStairs(int[] cost) {
int length = cost.length;
// 初始化动态规划数组
int[] dp = new int[length + 1];
// 边界条件
dp[0] = 0;
dp[1] = 0;
// 动态规划转移方程
for (int i = 2; i <= length; i++) {
// dp[i]是到达第i个台阶的最低花费
dp[i] = Math.min(dp[i - 1] + cost[i - 1], // 从上一个台阶上来的费用
dp[i - 2] + cost[i - 2]); // 从上上一个台阶上来的费用
}
// 返回到达楼梯顶部的最低花费
return dp[length];
}
}
时间复杂度
时间复杂度为O(n),其中n是cost
数组的长度。这是因为我们需要遍历整个数组一次,每次迭代的计算时间是常数级别的。
空间复杂度
空间复杂度为O(n),因为我们需要一个长度为n+1
的数组dp
来存储每个台阶的最低花费。
优化空间复杂度
实际上,我们并不需要存储所有的中间结果,只需要存储最后两个台阶的结果即可,因此可以进一步优化空间复杂度。
优化后的代码实现
class Solution {
public int minCostClimbingStairs(int[] cost) {
int length = cost.length;
// 只需要存储最后两个台阶的结果
int prev2 = 0; // 到达第0个台阶的最低花费
int prev1 = 0; // 到达第1个台阶的最低花费
int current = 0; // 当前台阶的最低花费
// 动态规划转移方程
for (int i = 2; i <= length; i++) {
current = Math.min(prev1 + cost[i - 1], prev2 + cost[i - 2]);
// 更新前两个台阶的结果
prev2 = prev1;
prev1 = current;
}
// 返回到达楼梯顶部的最低花费
return current;
}
}
优化后的空间复杂度
优化后的空间复杂度为O(1)。这是因为我们只存储了最后两个台阶的结果,不依赖于cost
数组的大小,所以空间复杂度是常数级别的。
文章持续跟新,可以微信搜一搜公众号 [ rain雨雨编程 ],第一时间阅读,涉及数据分析,机器学习,Java编程,爬虫,实战项目等。