对于具有数字元素的双向链表Q
,我们有一个指向第一个和最后一个元素的指针,我们定义了两个操作。
Delete (k): delete k first elements from Q.
Append (c), check the last element from `Q`, if this value bigger than c, delete this elements and repeat it again until the last element is lower or equal to `c` (or empty `Q`), then insert c as last elements of Q`.`
如果我们在空列表n
上以Q
次的任意顺序重复这两个操作的序列,那么这些操作的所有成本的总和接近2n
。为什么我的导师到达2n
?任何提示或想法都表示赞赏。
答案 0 :(得分:0)
如果我们以任意顺序重复这些操作n次空 list这些操作的所有成本的Q总和接近2n
它实际上是O(n)
,因为我们知道列表Q
是空的。
DoStuff(list Q, int n):
for(int i = 0; i < n; i++)
Q.Delete(k) //O(k)
Q.Append(c) //O(sizeof(Q))
//or
//Q.Append(c) //O(sizeof(Q))
//Q.Delete(k) //O(k)
其中n
是迭代次数。
现在说列表不是空的,那么我们就会O(n*(sizeof(Q)+k))
。对此的解释如下:
假设Delete (k)
更糟糕的情况是从Q
中删除k个第一个元素,其中k
的大小为Q
,那么我们将删除n个元素。但是,更准确地说O(k)
因为您始终只删除第一个k
元素。
假设Append (c)
的情况更糟,Q
内的所有元素都大于值c
。这将从尾节点开始,并从Q
删除所有节点。
按顺序
Delete(k) //O(k)
Append(c) //O(sizeof(Q))
或者
Append(c) //O(sizeof(Q))
Delete(k) //O(k)
更糟糕的情况是,这两个命令是O(sizeof(Q)+k)
。现在我们知道我们必须进行n
次迭代,所以我们最终得到O(n*(sizeof(Q)+k))
至于你的教授所说的,我能够 想象 你的教授说2n
的唯一原因是因为2
函数正在称为n
次。因此2n
。
答案 1 :(得分:0)
当我们在空列表Q 上以“Delete
次”的任意顺序“重复Append
和n
时,会调用Append
{{ 1}}次;因此,执行了n
列表元素插入。
由于列表最初为空,因此它永远不会包含超过n
个元素;因此,最多n
个列表元素删除是在n
和Delete
的组合中执行的。
因此Append
和Delete
中每个Append
中的循环总数不超过2 Append
。
总而言之,程序的任何部分执行时间超过2 n
次(单独计算列表元素插入,列表元素删除和列表元素访问可能常见的代码)。
当n
始终为0且k
非递减(包括始终为0)时,成本最低:我们有c
列表元素插入,n
列表元素读取(一个返回空),n
空白测试,n
元素比较,没有删除。因此,成本随参数变化很大。
注意:“这些操作的所有成本的总和接近2 n-1
”是不明确的,因此甚至没有错。更糟糕的是,如果列表元素删除,由于一些运气不好(例如代码缓存未命中,调试代码......)比其余部分慢得多,则可能是代码持续时间变化很大因素(远高于2),具体取决于参数。因此,执行时间不是总是“大约2 n
”,因为它的任何内容意义。
更新:在comment中,我们被告知列表元素插入和删除具有相同的成本1.有n
列表元素插入,以及0到n
列表元素删除。因此,如果我们忽略其他成本(合理的是内存分配成本占主导地位),总成本约为n
到约2 n
,具体取决于参数。此外,对于许多参数(包括大多数时间n
> = 1),列表元素删除几乎k
,因此如果坚持最好的话,成本约为2 n
猜测,例如在多项选择问题中使用(a)n
+ n
(b)k
(c)2 n
(d)3 n
作为唯一的选择。