# algorithms(算法)

# 1、重复计算的问题

int f(int n){
    // 1.先写递归结束条件
    if(n <= 2){
        return n;
    }
    // 2.接着写等价关系式
    return f(n-1) + f(n - 2);
}

看到没有,递归计算的时候,重复计算了两次 f(5),五次 f(4)。。。。这是非常恐怖的,n 越大,重复计算的就越多,所以我们必须进行优化。

如何优化?一般我们可以把我们计算的结果保证起来,例如把 f(4) 的计算结果保证起来,当再次要计算 f(4) 的时候,我们先判断一下,之前是否计算过,如果计算过,直接把 f(4) 的结果取出来就可以了,没有计算过的话,再递归计算。

用什么保存呢?可以用数组或者 HashMap 保存,我们用数组来保存把,把 n 作为我们的数组下标,f(n) 作为值,例如 arr[n] = f(n)f(n) 还没有计算过的时候,我们让 arr[n] 等于一个特殊值,例如 arr[n] = -1

当我们要判断的时候,如果 arr[n] = -1,则证明 f(n) 没有计算过,否则, f(n) 就已经计算过了,且 f(n) = arr[n]。直接把值取出来就行了。

// 我们实现假定 arr 数组已经初始化好的了。
int f(int n){
    if(n <= 1){
        return n;
    }
    //先判断有没计算过
    if(arr[n] != -1){
        //计算过,直接返回
        return arr[n];
    }else{
        // 没有计算过,递归计算,并且把结果保存到 arr数组里
        arr[n] = f(n-1) + f(n-2);
        reutrn arr[n];
    }
}

# 2、考虑是否可以自底向上

public int f(int n) {
   if(n <= 2)
       return n;
   int f1 = 1;
   int f2 = 2;
   int sum = 0;

   for (int i = 3; i <= n; i++) {
       sum = f1 + f2;
       f1 = f2;
       f2 = sum;
   }
   return sum;
}

这种方法,其实也被称之为递推。