斐波那契数Fibonacci
509. 斐波那契数
斐波那契数,通常用 F(n) 表示,形成的序列称为斐波那契数列。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
给定 N,计算 F(N)。
示例 1:
输入:2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1.
示例 2:
输入:3
输出:2
解释:F(3) = F(2) + F(1) = 1 + 1 = 2.
示例 3:
输入:4
输出:3
解释:F(4) = F(3) + F(2) = 2 + 1 = 3.
提示:
0 ≤ N ≤ 30
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/fibonacci-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
递归解法(Recursive)
// 时间复杂度 2^n,空间复杂度n
class Solution {
public int fib(int N) {
if (N < 2) return N;
return fib(N - 1) + fib(N - 2);
}
}
迭代(Iterative)
// 时间复杂度 n ,空间复杂度 1
class Solution {
public int fib(int N) {
if (N <= 1) return N;
int a = 0, b = 1;
while (N -- > 1) {
int sum = a + b;
a = b;
b = sum;
}
return b;
}
}
由顶到下,递归(Dynamic Programming - Top Down Approach)
// 时间复杂度降为n,空间为n
class Solution {
int[] cache = new int[31];
public int fib(int N) {
if (N <= 1) return N;
else if ( cache[N] != 0) return cache[N];
else return cache[N] = fib(N - 1) + fib(N - 2);
}
}
由下到上,计算到要求的值(Dynamic Programming - Bottom Up Approach)
//时间复杂度n,空间复杂度n
class Solution {
public int fib(int N) {
if (N<=1) return N;
return memoize(N);
}
public int memoize(int n){
int[] cache = new int[n+1];
cache[1] = 1;
for (int i=2;i <= n;i++) {
cache[i] = cache[i-1] + cache [i-2];
}
return cache[n];
}
}
873. 最长的斐波那契子序列的长度
如果序列 X_1, X_2, ..., X_n 满足下列条件,就说它是 斐波那契式 的:
n >= 3
对于所有 i + 2 <= n,都有 X_i + X_{i+1} = X_{i+2}
给定一个严格递增的正整数数组形成序列,找到 A 中最长的斐波那契式的子序列的长度。如果一个不存在,返回 0 。
(回想一下,子序列是从原序列 A 中派生出来的,它从 A 中删掉任意数量的元素(也可以不删),而不改变其余元素的顺序。例如, [3, 5, 8] 是 [3, 4, 5, 6, 7, 8] 的一个子序列)
示例 1:
输入: [1,2,3,4,5,6,7,8]
输出: 5
解释:
最长的斐波那契式子序列为:[1,2,3,5,8] 。
示例 2:
输入: [1,3,7,11,12,14,18]
输出: 3
解释:
最长的斐波那契式子序列有:
[1,11,12],[3,11,14] 以及 [7,11,18] 。
提示:
3 <= A.length <= 1000
1 <= A[0] < A[1] < ... < A[A.length - 1] <= 10^9
(对于以 Java,C,C++,以及 C# 的提交,时间限制被减少了 50%
思路
//思路1:两遍正序遍历+二分查找(或set)时间为O(N^2logN)
//不能用二分查找,需要找到两数之和之后循环查找,所以用HashSet
//思路2:动态规划,倒着推,状态转移方程最后第三个数到最大序列等于第二个加1
//再用hashMap存数据的,value为保存数据的索引,方便longest通过索引确定保存最大值的key
solution1
//时间复杂度为 O(n^2 log M)
class Solution {
public int lenLongestFibSubseq(int[] A) {
Set<Integer> s = new HashSet();
for (int i : A) s.add(i);
int len = A.length, ans = 0;
for (int i = 0; i < len; i++){
for (int j = i + 1; j < len; j++){
int a = A[j], b = A[i] + A[j];
if (b > A[len-1]) break;
int count = 2;
while(s.contains(b)){
int temp = b;
b += a;
a = temp;
ans = Math.max(ans,++count);
}
}
}
return ans >= 3 ? ans:0;
}
}
solution2
class Solution {
public int lenLongestFibSubseq(int[] A) {
Map<Integer,Integer> map = new HashMap();//保存原数组
Map<Integer,Integer> longest = new HashMap();//保存最大子序列,(k,i,j)key=k*len+i
int len = A.length, ans = 0;
for (int i = 0; i < len; ++i)
map.put(A[i], i);
for (int i = 0; i < len - 1; i++){
for (int j = i + 1; j < len; j++){
int mapk = A[j] - A[i];
int k = map.getOrDefault(A[j] - A[i], -1); //用map.get同时判断是否存在的一种方式
if (k >= 0 && k < i){
int count = longest.getOrDefault(k*len+i,2) + 1;//获取值默认为2,再加1
longest.put(i*len+j,count);
ans = Math.max(ans, count);
}
}
}
return ans >= 3 ? ans:0;
}
}