题目描述
n<=39
解题思路
方法一:递归
斐波那契数就是 1 1 2 3 5 8……每一项都等于前两项之和,刚开始学编程语言时就会想到递归,但是如果n非常大的时候,很容易stack overflow,由于本题n<=39的,所以还是通过了,但还是仅做对比就好。我觉得能递归的问题一般都是可以动态规划的 >///<
代码:
import java.util.*;
public class Solution {
public int Fibonacci(int n) {
int one=1;
int two=1;
if(n==0){
return 0;
}else if(n==1||n==2){
return 1;
}else
return Fibonacci(n-1)+Fibonacci(n-2);
}
}
运行时间:627ms
占用内存:9436k
方法一:动态规划
动态规划我一直觉得本质就是把递归反过来,斐波那契的每一项都仅仅依赖于前两项,通过以后看到别人的代码还有每次i++进行for循环的,相比起来i+2循环次数少,效率更高,因此运行时间短。
如果n不能被2整除,则返回那次循环中的第一个数,如果能被2整除则返回第二个。
【下面的代码是我尝试的时间最短的方法,如果有其他时间复杂度或者空间复杂度更优的解法欢迎讨论】
代码:
import java.util.*;
public class Solution {
public int Fibonacci(int n) {
int one=1;
int two=1;
if(n==0){
return 0;
}
for(int i=3;i<=n;i=i+2){
one=one+two;
two=one+two;
}
if(n%2==0){
return two;
}else{
return one;
}
}
}
运行时间:11ms
占用内存:9268k
===============================================================
斐波那契数列扩展——跳台阶问题
题目描述
解题思路
假如一只青蛙要跳到第10阶台阶,那么它有可能是从9跳上来的,9到10只有一种跳法;还有可能是从8跳上来的,8到10有一种跳法。当青蛙要跳到1阶时只有一种跳法,跳到2阶时有两种跳法,所以 f(1)=1,f(2)=2。
动态规划:
public class Solution {
public int JumpFloor(int target) {
//f(n)=f(n-1)+f(n-2)
int one=1;
int two=2;
if(target<3){
return target;
}
for(int i=3;i<=target;i+=2){
one=one+two;
two=one+two;
}
if(target%2==0){
return two;
}else{
return one;
}
}
}
运行时间:11ms
占用内存:9160k
递归:
public class Solution {
public int JumpFloor(int target) {
//f(n)=f(n-1)+f(n-2)
if(target==1){
return 1;
}else if(target==2){
return 2;
}else
return JumpFloor(target-1)+JumpFloor(target-2);
}
}
运行时间:513ms
占用内存:9304k
题外话:看到别的筒子有使用i++循环的,我也对运行时间和内存进行了测试,运行时间基本是在11ms-20ms不等,相差不是很多,可能是因为我的写法中虽然i+2减少了循环次数,但是判断n是否能被2整除时会花费一点时间。我觉得在n非常大时递归肯定是不推荐的,可能会stack overflow,i+2这样的循环较少的写法还是更好一些。
===============================================================
跳台阶扩展——变态跳台阶问题
题目描述
解题思路
青蛙跳到n阶有f(n)=f(n-1)+f(n-2)+f(n-3)+……+f(1)中跳法,
而跳到n-1阶有f(n-1)=f(n-2)+f(n-3)+……+f(1)种跳法,代入上式得
f(n)=2*f(n-1),每一个台阶的跳法只依赖于上一个状态
而青蛙跳到1阶有f(1)=1种跳法,跳到2阶有f(2)=2种跳法也满足f(n)=2*f(n-1)
依然是可以用递归或者动态规划
递归:
public class Solution {
public int JumpFloorII(int target) {
if(target==1){
return 1;
}else
return 2*JumpFloorII(target-1);
}
}
运行时间:19ms
占用内存:8684k
动态规划:
public class Solution {
public int JumpFloorII(int target) {
//f(n-1)=f(n-2)+f(n-3)+……+f(1)+f(0)
//f(n)=f(n-1)+f(n-2)+f(n-3)+……+f(1)+f(0)=2*f(n-1)
int temp=1;
if(target==1){
return temp;
}else{
for(int i=2;i<=target;i++){
temp=2*temp;
}
}
return temp;
}
}
运行时间:18ms
占用内存:8828k
===============================================================
扩展-矩形覆盖
题目描述
解题思路
在word里画了个图方便描述:
因此可以归纳出f(n)=f(n-1)+f(n-2),就是一个斐波那契数列的应用,依然可以使用递归或者动态规划,但是用递归可能会出现栈溢出的现象
代码
public class Solution { public int RectCover(int target) { int one=1; int two=2; int t; if(target==0||target==1||target==2){ return target; }else for(int i=3;i<=target;i++){ t=one; one=two; two=one+t; } return two; } }
运行时间:10ms
占用内存:9280k