题目:斐波那契数列
题目描述:大家都知道斐波那契数列,现在要求输入一个正整数 n ,请你输出斐波那契数列的第 n 项。
斐波那契数列是一个满足 fib(x)=1,x = 1,2;fib(x)=fib(x - 1) + fib(x - 2) , x > 2 的数列
数据范围:1≤n≤40
要求:空间复杂度 O(1),时间复杂度O(n) ,本题也有时间复杂度O(logn) 的解法
输入描述:一个正整数n
返回值描述:输出一个正整数
示例1:
输入:4
返回值:3
说明:根据斐波那契数列的定义可知,fib(1) = 1, fib(2) = 1,fib(3) = fib(3 - 1) + fib(3 - 2) = 2,fib(4) = fib(4 - 1) + fib(4 - 2) = 3,所以答案为3。
示例2:
输入:1
返回值:1
示例3:
输入:2
返回值:1
方法一:迭代方法
基本思想:斐波那契数列的特点是,第 n 个数等于第 n - 1 个数和第n - 2 个数的和。那么我们利用这个特点就可以迭代求出第 n 个数的值。
代码实现:
public int Fibonacci(int n) {
if(n == 0){
return 0;
}
int first = 1;
int second = 1;
int third = 1;
// 如果 n = 0,那么fib(n) = 0,之前就直接返回了
// 如果 n = 1,那么fib(n) = 1,是 third 的值
// 如果 n = 2,那么fib(n) = 1,是 third 的值
// n > 2时,所有的数都满足下面的循环
while(n > 2){
third = first + second;
first = second;
second = third;
n--;
}
return third;
}
方法二:
基本思想:根据斐波那契数列的特点,我们可以把这个问题看做是一个递归问题,问题规模慢慢变小,但是本质是相同的,这时我们就用分治的思想。
代码实现:
public int Fibonacci(int n){
if(n == 0){
return 0;
}
if(n < 3){
return 1;
}
// 当n != 0,1,2时,我们就使用递归求解
return Fibonacci1(n - 1) + Fibonacci1(n-2);
}
虽然方法二的递归方法可以解决这个问题,但是耗费的时间太长,所以我们对这个方法进行改良。
方法二(改良版):
基本思想:我们利用一个 map 来将斐波那契数列的各项保存,这样就不会反复计算已经计算过的数,可以节省时间。
代码实现:
private Map<Integer,Integer> map = new HashMap<>();
public int Fibonacci2(int n){
if(n == 0){
return 0;
}
if(n <= 2){
return 1;
}
// 前前一个
int ppre = 0;
// 判断 map 中是否包含这个值,不包含就添加进去,包含就直接取出来用
if(map.containsKey(n - 2)){
ppre = map.get(n - 2);
}else{
ppre = Fibonacci2(n - 2);
map.put(n - 2,ppre);
}
// 前一个
int pre = 0;
//判断 map 中是否包含这个值,不包含就添加进去,包含就直接取出来用
if(map.containsKey(n - 1)){
pre = map.get(n - 1);
}else{
pre = Fibonacci2(n - 1);
map.put(n - 1,pre);
}
// 最后就直接返回 前一个数和前前一个数的和
return pre + ppre;
}