斐波那契
先看斐波拉契递归的朴素版本:
int fib1(int n) {
if(n < 2)
return n;
else
return fib1(n-1) + fib1(n-2);`
}
这段代码的意思是:第n个数等于前两个数之和。但 f(1) = 1, f(0) = 0, 这两个特殊值作为递归出口。
优化:
尾递归:
int fib_wei(int n , int a, int b) {
if(n < 2)
return n;
if(n == 2)
return b;
return (n-1, b, a+b);
}
int main() {
fib_wei(n, 1, 1);
return 0;
}
这段代码明显可读性比朴素版本低,但优点在于将时间复杂度从O(2n) 变成了O(n),利用尾递归的特性做了一个自底向上的运算,相当于迭代。但是比迭代看起来更简洁。
DP版本:
int fib(int n) {
int arr[2] = {0, 1};
for(int i = 2; i <= n; ++i) {
arr[i & 1] = (arr[0] + arr[1]) % (int)(1e9 + 7);
}
return arr[n & 1];
}
};
这个解题思路是在leetcode上看到的一位大佬的解题,斐波拉契的迭代思路,就是典型的DP思路,其延申式为arr[n] = arr[n-1] + arr[n-2],和尾递归一样,思路应该是自底向上,时间复杂度O(n)已经没法优化,但是作者将空间复杂度优化为了O(1)。正整数为偶数和奇数,奇数和偶数与1相与就只有1,和,0两个结果。
从变化上,从F(2) = F(1) + F(0), 由于10 & 01等于0,0应该被更新, f(3) = f(2) + f(1) , 这里1应该被更新。总结:偶数更新,arr[0],奇数更新arr[1]。
启示:要做运算的数据,可以以另一种形式储存。(位运算)
以下是其解题链接
作者Leetcode解题链接