03算法复杂度(下)

文章目录

  • 1.最好情况时间复杂度(best case time complexity)
  • 2.最坏情况时间复杂度(worst case time complexity)
  • 3.平均情况时间复杂度(average case time complexity)
  • 4.均摊时间复杂度(amortized time complexity)

1.最好情况时间复杂度(best case time complexity)

最好情况时间复杂度:在最理性的情况下,执行这段代码的时间复杂度,比如下面的代码中,最好的情况,x为arr的第一个元素,则时间复杂度为O(1):

/**
     * 最好:O(1)
     * 最坏:n -> O(n)
     * 平均: x的位置可能在 0,1,...n-1 以及 不在arr中, 共n+1种情况,每种情况的概率为 1/(n+1)
* 因此,平均复杂度为: 1 * ( 1/(n+1) ) + 2 * ( 1/(n+1) ) + ... + n * ( 1/(n+1) ) + n *( 1/(n+1) ) = ( n(n+3) )/ ( 2* (n+1) * -> O(n) * @param arr * @param n * @param x * @return */
public static int cal2(int [] arr, int n, int x) { // 总 n -> O(n)? int i = 0; // 1 int pos = -1; // 1 for(; i < n; ++i) { // n? if(arr[i] == x) { // n? pos = i; // n? break; } } return pos; }

2.最坏情况时间复杂度(worst case time complexity)

最坏情况复杂度,就是在最糟糕的情况下,执行这段代码的时间复杂度,如下的代码中,如果arr中无x, 则需要把整个arr都遍历一遍,复杂度为O(n):

/**
     * 最好:O(1)
     * 最坏:n -> O(n)
     * 平均: x的位置可能在 0,1,...n-1 以及 不在arr中, 共n+1种情况,每种情况的概率为 1/(n+1)
* 因此,平均复杂度为: 1 * ( 1/(n+1) ) + 2 * ( 1/(n+1) ) + ... + n * ( 1/(n+1) ) + n *( 1/(n+1) ) = ( n(n+3) )/ ( 2* (n+1) * -> O(n) * @param arr * @param n * @param x * @return */
public static int cal2(int [] arr, int n, int x) { // 总 n -> O(n)? int i = 0; // 1 int pos = -1; // 1 for(; i < n; ++i) { // n? if(arr[i] == x) { // n? pos = i; // n? break; } } return pos; }

3.平均情况时间复杂度(average case time complexity)

最好、最坏时间复杂度其实都是极端情况下的代码复杂度,发生的概率并不大,具有普适性的还是平均时间负责度

  • 粗略平均:

    x的位置可能在 0,1,...n-1 以及 不在arr中, 共n+1种情况,累加再除以n+1得平均时间:
    (1+2+3+...+n+n)/ (n+1) = ( n(n+3) )/ ( 2* (n+1)  -> O(n)
    
  • 精准平均:运用概率统计,

    精准平均: x的位置可能在 0,1,...n-1 以及 不在arr中, 共n+1种情况,每种情况的概率为 1/2,而数组中每个元素的概率为1/n:
         因此,平均复杂度为: 1*(1/2)*(1/n) + 2*(1/2)*(1/n) + 3*(1/2)*(1/n) + ... + n*(1/2)(1/n) + n*(1/2) = (3n+1)/4 -> O(n)
    

    这个值就是概率论中的加权平均值,也叫做期望值,所以平均时间复杂度的全称应该叫做加权平均时间复杂度 或者 期望时间复杂度

    /**
         * 最好:O(1)
         * 最坏:n -> O(n)
         * 粗略平均: x的位置可能在 0,1,...n-1 以及 不在arr中, 共n+1种情况,累加再除以n+1得平均时间:
    * ( 1+2+3+...+n+n)/ (n+1) = ( n(n+3) )/ ( 2* (n+1) * -> O(n) * 精准平均: x的位置可能在 0,1,...n-1 以及 不在arr中, 共n+1种情况,每种情况的概率为 1/2,而数组中每个元素的概率为1/n
    * 因此,平均复杂度为: 1*(1/2)*(1/n) + 2*(1/2)*(1/n) + 3*(1/2)*(1/n) + ... + n*(1/2)*(1/n) + n*(1/2) = (3n+1)/4 * -> O(n) * @param arr * @param n * @param x * @return */
    public static int cal2(int [] arr, int n, int x) { // 总 n -> O(n)? int i = 0; // 1 int pos = -1; // 1 for(; i < n; ++i) { // n? if(arr[i] == x) { // n? pos = i; // n? break; } } return pos; }

4.均摊时间复杂度(amortized time complexity)

/**
     * 最好:只一次 O(1)
     * 最差: n+n -> 2n -> O(n)
     * 平均: 1*( 1/(n+1) ) + 1*( 1/(n+1) ) + ...+ n * ( 1/(n+1) ) = n/2n+2 -> O(1)
     * 均摊: O(1): 前n次 都为O(1), 每隔n+1次,复杂度为O(n), 把这n次操作均摊到
* 前面的n次,总的复杂度为 O(1). * @param val * @param n */
public static void insert(int val, int n) { int[] arr = new int[n]; int count = 0; if(count == arr.length) { // 1 int sum = 0; // 1 for(int i=0; i < arr.length; i++) { // count == arr.length ? n : 0 sum = sum + arr[i]; // count == arr.length ? n : 0 } arr[0] = sum; // count == arr.length ? 1 : 0 count = 1; // count == arr.length ? 1 : 0 } arr[count] = val; // 1 ++count; // 1 }

均摊其实是平均的一种特殊情况,特点:

对于 insert() 函数来说,O(1) 时间复杂度的插入和 O(n) 时间复杂度的插入,出现的频率是非常有规律的,而且有一定的前后时序关系,一般都是一个 O(n) 插入之后,紧跟着 n-1O(1) 的插入操作,循环往复。
每一次 O(n) 的插入操作,都会跟着 n-1O(1) 的插入操作,所以把耗时多的那次操作均摊到接下来的 n-1 次耗时少的操作上,均摊下来,这一组连续的操作的均摊时间复杂度就是 O(1)

你可能感兴趣的:(数据结构与算法,数据结构学习笔记)