复杂度分析(下)

+文本内容是对王争《数据结构与算法之美》课程的笔记, 如果有任何侵权行为, 请联系博主删除

最好、最坏时间复杂度

先给个例子:

// n 表示数组 array 的长度
int find(int[] array, int n, int x){
    int i = 0;
    int pos = -1;
    for(; i<n; ++i){
        if (array[i] == x){
            pos = i;
        }
    }
    return pos
}

按照上次的分析方法, 这段代码的复杂度是O(n), 其中, n代表数组的长度.

但是在数组中查找一个数据, 不需要从头到尾遍历一遍, 在中间可能就可以提前结束循环. 优化代码.

// n 表示数组 array 的长度
int find(int[] array, int n, int x){
    int i = 0;
    int pos = -1;
    for(; i<n; ++i){
        if(array[i] == x){
            pos = i;
            break;
        }
    }
    return pos;
}

如果数组的第一个元素正好是要查找的变量x, 那时间复杂度是O(1). 但是如果数组中不存在变量x, 那时间复杂度是O(n).

由此引入三个概念: 最好情况时间复杂度、最坏情况时间复杂度和平均情况复杂度.

最好情况时间复杂度和最坏情况时间复杂度都很好理解, 重点记录一下平均情况时间复杂度.

平均情况时间复杂度

查找变量x在数组中的位置, 有n+1种情况: 在数组的0 \sim n-1位置中和不在数组中. 把每种情况下, 需要遍历的元素累加起来, 然后再除以n+1, 就可以得到需要遍历的元素个数的平均值, 即:
\frac{1+2+3+\cdots+n-1+n}{n+1} = \frac{n(n+3)}{2(n+1)}
将其简化后可得O(n). 但是, 这个结果是有问题的, 因为每种情况出现的概率不一样.

要查找的变量x, 要么在数组里, 要么不在数组里. 为了方便理解, 假设在数组中与不在数组中的概率都为\frac{1}{2}. 另外, 要查找的数据出现在0 \sim n-1n个位置的概率也是一样的, 为\frac{1}{n}. 所以, 根据概率乘法法则, 要查找的数据出现在0 \sim n-1中任意位置的概率就是\frac{1}{2n}.

计算过程为:
1 \times \frac{1}{2n}+2 \times \frac{1}{2n}+3\times\frac{1}{2n}+ \cdots +n \times \frac{1}{2n} + n \times \frac{1}{2} = \frac{3n+1}{4}
这个值就是概率论中的加权平均值, 也叫作期望值, 所以平均时间复杂度的全称应该叫加权平均时间复杂度或者期望时间复杂度.

这段代码的加权平均时间复杂度仍然是O(n).

均摊时间复杂度

均摊时间复杂度, 听起来跟平均时间复杂度有点儿像. 但是, 其应用场景更加特殊、更加有限.

// array 表示一个长度为 n 的数组
// 代码中的 array.length 就等于 n
int[] array = new int[n];
int count = 0;

void insert(int val){
    if(count == array.length){
        int sum = 0;
        for(int i=0; i<array.length; ++i){
            sum = sum + array[i];
        }
        array[0] = sum;
        count = 1;
    }
    array[count] = val;
    ++count;
}

最理想的情况是, 数组中有空闲空间, 我们只需要将数据插入到数组下表为count的位置就可以了, 所以最好情况时间复杂度为O(1). 最坏的情况下, 数组中没有空闲空间了, 我们需要先做一次数组的遍历求和, 然后再将数据插入, 所以最坏情况时间复杂度为O(n).

而平均时间复杂度是O(1). 我们还是可以通过概率论的方法来分析.

假设数组的长度是n, 根据数据插入的位置的不同, 我们可以分为n种情况, 每种情况的时间复杂度是O(1). 除此之外, 还有一种"额外"的情况, 就是在数组没有空闲空间时插入一个数据, 这个时候的时间复杂度是O(n). 而且, 这n+1种情况发生的概率一样, 都是\frac{1}{n+1}. 所以, 根据加权平均的计算方法, 我们求得的平均时间复杂度就是:
1 \times \frac{1}{n+1}+1\times\frac{1}{n+1}+\cdots+1\times\frac{1}{n+1}+n\times\frac{1}{n+1} = O(1)
其实这个例子不需要引入概率论的知识, 对比一下insert()find()的例子, 就会发现这两者有很大的差别.

首先, find()在极端情况下, 复杂度才为O(1). 但insert()在大部分情况下, 时间复杂度都为O(1). 只有个别情况下, 复杂度才为O(n). 这是insert()第一个区别与find()的地方.

第二个不同点, 对于insert()函数来说, O(1)时间复杂度的插入和O(n)时间复杂度的插入, 出现的频率是非常有规律的, 而且有一定的前后时序关系, 一般都是一个O(n)插入之后, 紧跟着n-1O(1)的插入操作, 循环往复.

针对这样一种特殊场景的复杂度分析, 我们并不需要像之前那样, 找出所有的输入情况及相应的发生概率, 然后计算加权平均值. 为此, 引入一种更加简洁的分析方法: 摊还分析法, 通过摊还分析法得到的时间复杂度我们起了一个名字, 叫均摊时间复杂度.

针对上述例子, 每一次O(n)的插入操作, 都会跟着n-1O(1)的插入操作, 所以把耗时多的那次操作均摊到接下来的n-1次耗时少的操作上, 均摊下来, 这一组连续的操作的均摊时间复杂度就是O(1).

总结其应用场景:

对一个数据结构进行一组连续操作中, 大部分情况下时间复杂度都很低, 只有个别情况下时间复杂度比较高, 而且这些操作之间存在前后连贯的时序关系, 这个时候, 我们就可以将一组操作放在一块儿分析, 看是否能将较高时间复杂度那次操作的耗时, 平摊到其他那些时间复杂度比较低的操作上. 而且, 能够应用均摊时间复杂度分析的场合, 一般均摊时间复杂度就等于最好情况时间复杂度.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342