每天刷一道算法题…希望自己能入坑
1.题目描述
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1 阶 + 1 阶
2 阶
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1 阶 + 1 阶 + 1 阶
1 阶 + 2 阶
2 阶 + 1 阶
分析:
根据这道题的题目条件,每次只能爬1或者2个楼梯。那么可以想到,当前楼梯的走法 是 前一个楼梯 和前两个楼梯上走法之和(博客中走迷宫。的情景类似。)。因为他可以从当前楼梯的前一个上跳过来(跳一步);从前两个的楼梯上跳过来(跳两步)。 从而我们可以知道关系表达式F(N) = F(N-2)+F(N-1)(N>=2时)
解法一:递归
int genTime(int n){
if (n==1||n==2) return n;
return genTime(n-2)+genTime(n-1);
}
但是提交到leetcode上的时候,当用例n=45时 显示超时。无法通过。因为在递归的时候有着大量的重复子结构被计算,这种子结构的我们可以采用自底向上的解题方法,使用动态规划
解法二:动态规划
动态转移方程:f(n) = f(n-1) + f(n-2)。我们就可以利用动态转移方程,自底向上的求出F(n)
int _gen(int n){
int [] f = new int[n];
f[0] = 1;
f[1] = 2;
for(int i = 2;i<n;i++){
f[i] = f[i-1] + f[i-2];
}
return f[n-1];
}
结果是 虽然通过了 。但是效率和 内存的效果上都没太好。稍微想一下之后,发现是因为我们使用了数组 维护了整个F(n)关系,这种即消耗了大量的内存。优化方式 我们只需要使用临时变量,不断的存储当前值 。从而计算出f(n) 代码如下:
int _gen2(int n ){
if (n<=2) return n;
int start = 3;
int temp1 = 1;
int temp2 = 2;
int target = 0;
while (start<=n){
target = temp1 +temp2;
temp1 = temp2;
temp2 = target;
start++;
}
return target;
}
这样效率就提高很多。