算法之动态规划 -- Fibonacci

283 阅读1分钟

Those who cannot remember the past are condemned to repeat it.

忘记过去的人,必将重蹈覆辙。

动态编程:把大问题分解成小问题,小问题的最优解是大问题的组成部分。

斐波那契数列解决方案:

    1. 最原始的解决方案:使用递归来解决。时间复杂度是指数级的,计算过的数值还会重新计算,浪费时间。
int fibonacciOne(int index){
    if(index <= 1){
        return 1;
    }
    int result = fibonacciOne(index-1)+fibonacciOne(index-2);
    return result;
}
    1. 添加memoize方法,也就是加一个勿忘过去的标识,那就加一个map来存储已经计算过的值,省的浪费无谓的时间.
Map<int,int> map = {};
int fibonacciTwo(int index){
    if(map.containsKey(index)){
        return map[index];
    }
    int result = 0;
    if(index <= 1){
        result = 1;
    }else{
        result = fibonacciTwo(index-1) + fibonacciTwo(index-2);
    }
    map[index] = result;
    return result;
}
  • 3.以上两种方案都是自顶向上,也就是从大问题开始向小问题一步步靠近。但是我们也可以使用自底向上的方式来解决,先从小问题开始解决,再一步步扩展到目标问题。这样就可以使用空间复杂度O(1)来解决问题。
int fibonacciThree(int index){
    int first = 1;
    int second = 1;
    int result = first;
    for(int i = 2; i<=index; i++){
        result = first + second;
        second = first;
        first = result;
    }
    return result;
}

额外的解决方法扩展:使用矩阵实现O(logN)的复杂度、使用Fn = {[(√5 + 1)/2] ^ n} / √5实现O(1)复杂度.