动态规划、回溯、贪心,分治

动态规划篇算法

  • 从斐波那契数列开始

咱们先给出斐波那契数列的经常使用算法类缓存

public class Fibonacci {
    private static int num = 0;
    private Fibonacci() {
    }
    public static int fib(int n) {
        num++;
        if (n == 0) {
            return 0;
        }
        if (n == 1) {
            return 1;
        }
        return fib(n - 1) + fib(n - 2);
    }

    public static void main(String[] args) {
        num = 0;
        int n = 20;
        long start = System.nanoTime();
        int res = Fibonacci.fib(n);
        long end = System.nanoTime();
        System.out.println(res);
        System.out.println((end - start) / 1000000000.0);
        System.out.println(num);
    }
}

运行结果spa

6765
3.96599E-4
21891blog

此时咱们调大n的值为40ci

运行结果get

102334155
0.473162902
331160281class

再调大n的值为42List

267914296
1.302307318
866988873搜索

咱们能够看到此处随着n的增大,时间是几何倍数增加,由此咱们可知斐波那契数列的时间复杂度为O(2^n)im

但咱们发现斐波那契数列的存在着大量的重复计算,以下图所示,咱们来看计算一个n=5的时候都有哪些重复计算的地方

在这里咱们能够看到3被计算了2次。

而2则被计算了3次,这仍是n = 5的状况下,若是随着n值的增大,重复计算的次数就会愈来愈多。

因此咱们给出了一个新的记录重复计算值不须要从新计算的斐波那契算法类

public class Fibonacci {
    private static int num = 0;
    private static List<Integer> memo = new ArrayList<>();
    private Fibonacci() {
    }
    //记忆化搜索
    public static int fib(int n) {
        num++;
        if (n == 0) {
            return 0;
        }
        if (n == 1) {
            return 1;
        }
        if (memo.get(n) == -1) {
            memo.set(n,fib(n - 1) + fib(n - 2));
        }
        return memo.get(n);
    }

    public static void main(String[] args) {
        num = 0;
        int n = 42;
        for (int i = 0;i <= n;i++) {
            memo.add(-1);
        }
        long start = System.nanoTime();
        int res = Fibonacci.fib(n);
        long end = System.nanoTime();
        System.out.println(res);
        System.out.println((end - start) / 1000000000.0);
        System.out.println(num);
    }
}

此次咱们再来计算n = 42,运行结果

267914296
4.2859E-5
83

由结果可知,当咱们减小了计算次数,斐波那契算法的时间复杂度从O(2^n)一会儿降到了O(n)级别,这就至关于咱们在列表中命中了缓存,无需866988873次计算,而计算次数只下降到了83次。

相关文章
相关标签/搜索