1.算法复杂度

什么是算法?

算法是用于解决特定问题的一系列的执行步骤,使用不同算法,解决痛一个问题,效率可能相差非常大.

求第 n 个斐波那契数

package zh.algorithm;

public class Fibonacci {
    // 方法1:递归,因为fib(n)必须要计算前面两个数,所以复杂度为2*2*2....=2n

public static int fib(int n) { if (n <= 1) return n; return fib(n - 1) + fib(n - 2); } // 方法2:循环,复杂度为O(n) public static int fib2(int n) { if (n <= 1) return n; int first = 0; int second = 1; for (int i = 0; i < n - 1; i++) { int sum = first + second; first = second; second = sum; } return second; } public static void main(String[] args) { // System.out.println(fib(0)); // System.out.println(fib(1)); // System.out.println(fib(2)); // System.out.println(fib(3)); // System.out.println(fib(4)); // System.out.println(fib(5)); // Output:0 1 1 2 3 5 System.out.println(fib2(64));// Output 1640636603 } }

如何评判一个算法的好坏

方法1:比较不同算法对同一组输入的执行处理时间(事后统计法),缺点

  • 执行时间严重依赖硬件以及运行时各种不确定的环境因素
  • 必须编写相应的测算时间代码
  • 测试数据的选择难以保证公正性

方法2:从以下维度来评估算法的优劣:

  • 正确性,可读性,健壮性(对不合理输入的反应能力和处理能力)
  • 时间复杂度(time complexity):估算程序指令的执行次数(执行时间)
  • 空间复杂度(space complexity):估算所需占用的存储空间

大O表示法

一般用大O表示法来描述复杂度,它表示的是数据规模n对应的复杂度,可以忽略常数,系数,低阶.

  • 9 >> O(1)
  • 2n+3 >> O(n)
  • n2+2n+6 >> O(n2)
  • 4n3+3n2+22n+100 >>O(n3)
  • log2n,log3n,log8n >>logn

复杂度排序

O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)

而通常时间复杂度与运行时间有一些常见的比例关系:

复杂度 10 20 50 100 1000 10000 100000
O(1)

<1s

<1s

<1s

<1s

<1s

<1s

<1s

O(log2(n))

<1s

<1s

<1s

<1s

<1s

<1s

<1s

O(n)

<1s

<1s

<1s

<1s

<1s

<1s

<1s

O(n*log2(n))

<1s

<1s

<1s

<1s

<1s

<1s

<1s

O(n2)

<1s

<1s

<1s

<1s

<1s

2s

3-4 min

O(n3)

<1s

<1s

<1s

<1s

20s

 5 hours 

 231 days 

O(2n)

<1s

<1s

 260 days 

 hangs 

 hangs 

hangs

hangs

O(n!)

<1s

 hangs 

hangs

 hangs 

hangs

hangs

hangs

O(nn)

 3-4 min 

hangs

hangs

 hangs 

hangs

hangs

hangs

常见复杂度分析

public class Main {
    
    /* 0 1 2 3 4 5
     * 0 1 1 2 3 5 8 13 ....
     */
    
    // O(2^n)
    public static int fib1(int n) {
        if (n <= 1) return n;
        return fib1(n - 1) + fib1(n - 2);
    }
    
    // O(n)
    public static int fib2(int n) {
        if (n <= 1) return n;
        
        int first = 0;
        int second = 1;
        for (int i = 0; i < n - 1; i++) {
            int sum = first + second;
            first = second;
            second = sum;
        }
        return second;
    }public static void test1(int n) {// 1
        if (n > 10) { 
            System.out.println("n > 10");
        } else if (n > 5) { // 2
            System.out.println("n > 5");
        } else {
            System.out.println("n <= 5"); 
        }
        
        // 1 + 4 + 4 + 4
        for (int i = 0; i < 4; i++) {
            System.out.println("test");
        }
        
        // 140000
        // O(1)
        // O(1)
    }

    public static void test2(int n) {
        // O(n)
        // 1 + 3n
        for (int i = 0; i < n; i++) {
            System.out.println("test");
        }
    }

    public static void test3(int n) {
        // 1 + 2n + n * (1 + 3n)
        // 1 + 2n + n + 3n^2
        // 3n^2 + 3n + 1
        // O(n^2)
        
        // O(n)
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                System.out.println("test");
            }
        }
    }

    public static void test4(int n) {
        // 1 + 2n + n * (1 + 45)
        // 1 + 2n + 46n
        // 48n + 1
        // O(n)
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < 15; j++) {
                System.out.println("test");
            }
        }
    }

    public static void test5(int n) {
        // 8 = 2^3
        // 16 = 2^4
        
        // 3 = log2(8)
        // 4 = log2(16)
        
        // 执行次数 = log2(n)
        // O(logn)
        while ((n = n / 2) > 0) {
            System.out.println("test");
        }
    }

    public static void test6(int n) {
        // log5(n)
        // O(logn)
        while ((n = n / 5) > 0) {
            System.out.println("test");
        }
    }

    public static void test7(int n) {
        // 1 + 2*log2(n) + log2(n) * (1 + 3n)
        
        // 1 + 3*log2(n) + 2 * nlog2(n)
        // O(nlogn)
        for (int i = 1; i < n; i = i * 2) {
            // 1 + 3n
            for (int j = 0; j < n; j++) {
                System.out.println("test");
            }
        }
    }

    public static void test10(int n) {
        // O(n)
        int a = 10;
        int b = 20;
        int c = a + b;
        int[] array = new int[n];
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i] + c);
        }
    }
}

 

posted @ 2020-05-21 00:03  大碗炸酱面  阅读(245)  评论(0编辑  收藏  举报