题目描述:
已知两个长度分别为m和n的升序列表,若将它们合并为一个长度为m+n的降序列表,则最坏情况下的时间复杂度是(D)
A. O(n)
B. O(mn)
C. O(min(m,n))
D. O(max(m,n))
关于这题,我先看过一些博客,最后又加上自己的思考,最终进行梳理:
核心是:分别设置两个指针指向两个列表的第一个元素,然后进行比较,更小的就拎出来放在一个新的列表中,之后指针后移一位,以此类推
- 注意:将一个列表逆置的时间复杂度是 O(列表的长度)
首先, 先思考一下最好的情况
是怎样的呢?
不难想到,就是第一个列表的最后一个数 会 小于等于 第二个列表的第一个数,且第一个列表长度更小,这样就让比较次数达到最少,如:
列表 A: 1 2 3
列表 B: 4 5 6 7 8 9
这样可以容易得到,列表B的第一个数“4”,依次和列表A的数进行比较,则结果是O(min(m,n))
可以看出,思路就是怎么样能使得比较次数最少,就是最好的情况,而这个情况就是使得更短的列表的最后一个数被比较到了。
那反过来,最坏的情况,不就是使得比较次数最多
吗?
怎样能使得比较次数最多呢?可能会想那不就是最长的列表的最后一个数被比较到了,如下,列表A的第一个数“10”不断地和B中的所有数进行比较:
列表 A: 10 11 12
列表 B: 4 5 6 7 8 9
但是,这真的是最坏的情况吗,为什么不干脆让两个列表的最后一个数都进行了比较呢?这样比较次数不是更多吗?比如说(假设a<b,不就存在 a<b<a+b 吗?),如下图:
列表A:1 100
列表B: 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ..... 101
上面这种情况,就是列表A的“1” 先和 列表B的“2”进行比较,之后从 列表B的 “2”~“100”都和列表A的最后一个数“100”进行比较,最后列表B的最后一个数“101”再和列表A的“100”进行比较。
总共比较次数是:1+(100-2+1)+1=101 次
(也可以自己再多想几个例子,下面会讲解为什么这样是比较次数最多的情况)
列表A长度为2,列表B长度为 100 ,则 m+n=102
,比较次数为 m+n-1 = 101次。
选项中没有O(m+n),我们可以再继续思考,计算时间复杂的有一个加法规则:
那么T(n)=O(m)+O(n)=O(max(m,n))
不是就可以成立了吗?(O(1)忽略不计),或者换一个角度想:
假设m=2,n不止等于100呢,等于1000,10000, 100000000000呢?那么当n很大很大的时候,加了2和没有2又有什么区别呢?
所以,最后答案是D。
写这个题目的时候,我发现答案解析很简洁,就是说,最差情况是两个列表的数依次比较。
又找了一些博客看,有说是两个列表相互交错,都让我有一些没反应过来。
后面自己想清楚了才知道,就是指:(看下面的代码)a1<=b1,a5<=a8,这样的话,a1 (列表A的首)和a8(列表B的尾)一定在新的列表的两端
,那么这两个列表其余的数(a1之后的数 和 b8之前的数)怎么可能不进行依次比较呢?
列表A: a1 a2 a3 a4 a5
列表b: b1 b2 b3 b4 b5 b6 b7 b8
这样的话无论怎样都会进行交错(极端的情况就是上面的例子,列表B的前99个数都>=1, 且<= 100,最后一个数一定大于100,这样形成了交错)
写下这按文章,是因为觉得自己看了很多思路又思考了很久后,最终想出的思路还挺好理解的,也想记录下自己的思考,哪怕只是一个很小的问题,很小的点,也能为接下来的复习增添动力。如有觉得这篇文章有任何疑问或不正确,欢迎指正!