我必须完成实习的在线编程测试,并得到关于复杂性分析的问题。我回答了这个问题并且标记为错误,我只想了解原因,所以我可以改进。
问题:
当reverseOrder为true且为false时,给出以下算法的复杂性:
List<int> stackToList(Stack<int> stack, bool reverseOrder) {
List<int> items = new List<int>();
while (stack.Count > 0) {
int item = stack.Pop();
if (reverseOrder) {
items.Insert(0, item);
} else {
items.Add(item);
}
}
return items;
}
编辑:这是多项选择,可能的答案是:
您可以在reverseOrder为true时选择一个,为false时选择另一个。
我的回答:
我通过以下方式得到了这个答案:
n
次,因为它会继续,直到没有元素可以弹出Pop()
是O(1)
如果reverseOrder
为true
,则会在列表的前面生成Insert
。由于List<T>
由数组支持,因此会动态调整大小,并将每个元素向上移动一个空格,并将元素插入索引0.根据https://msdn.microsoft.com/en-us/library/sey5k5z4(v=vs.110).aspx:
此方法是O(n)操作,其中n是Count。
如果reverseOrder
为false
,则Add
会将项目附加到列表的后面。由于items
没有给出初始尺寸,Count
永远不会小于Capacity
,导致调整大小,因此根据https://msdn.microsoft.com/en-us/library/3wcytfd1(v=vs.110).aspx:
如果Count小于Capacity,则此方法为O(1)操作。如果需要增加容量以容纳新元素,则此方法将成为O(n)操作,其中n为Count。
此刻我感到非常沮丧,因为这个错误导致我的分数直线下降,即使我在测试中得到了所有其他问题也是正确的。
答案 0 :(得分:4)
您需要询问编写测试的人员。这里的任何答案都是严格意见的,因为我们没有完整的上下文,即什么会导致测试作者以不同的方式描述算法的复杂性。
那就是说,我会同意reverseOrder == false
场景中的测试作者。虽然在调用Add()
期间可能可能招致调整大小操作,但调整大小操作会在最坏情况下引入log N
成本,因为每个调整大小时新大小会加倍
你没有说出正确答案应该是什么,但我会把它作为O(N log N)。
答案 1 :(得分:1)
您的假设是每次添加项目时容量都会增加 - 这是不正确的。文档似乎没有提到确切的算法,但我相信每次容量增加时它都会翻倍。您可以在关于您链接的文档中的恐龙样本中看到它们 - 它们添加了5个恐龙,容量报告为8个。
答案 2 :(得分:0)
查看
的第6669行http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,cf7f4095e4de7646
很明显,在列表的开头插入会强制复制到列表的所有位置。所以每个插入都需要N次移动。 O(N ^ 2)它在我看来。
答案 3 :(得分:0)
stackToList(stack, true )= O(n)。大多数情况下,这个调用将是O(1)。但是,当List.Add函数必须扩展超过其容量时,需要将该数组复制到容量是之前两倍的新数组,并迭代前面的项目以将它们存储在新数组中。因此,我们可以将excel中的实际操作表示为IF(n LOG(n,2)(n / 2)/ INT(n LOG(n,2) (n / 2))= 1,n,1)。如果没有资源瓶颈,如果这个算法在10秒内完成1000万项,那么完成1亿个项目就可能需要大约10(10)秒。实际上,我们知道它会比Big O Notation预测稍差,因为O(n)操作将需要很多O(1)操作才能从中恢复。
stackToList(stack, false )= O(n ^ 2)。列表的insert函数执行数组副本,该副本必须将列表中的所有元素移动到新列表。当指针开始迭代通过父堆栈时,操作数从0开始,然后增长直到达到n。平均而言,它发生n / 2次。常量2在Big O表示法中删除,你留下n。如果没有资源瓶颈,如果这个算法在10秒内完成了1000万个项目,要完成1亿个项目,你可能需要大约10(10 ^ 2)秒。实际上,我们知道第二种情况比Big O Notation预测更好,因为它实际上是n *(n-1),但它不会比O(n * Log(n))更好地扩展,下一步下。
分解运营:
List<int> stackToList(Stack<int> stack, bool reverseOrder) {
List<int> items = new List<int>(); // O(1)
while (stack.Count > 0) { // O(n): For every int in the supplied stack
int item = stack.Pop(); // O(1): https://referencesource.microsoft.com/#System/compmod/system/collections/generic/stack.cs,222
if (reverseOrder) { // O(1)
items.Insert(0, item); // O(n^2): https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,669
} else {
items.Add(item); // O(Slightly more than 1): https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,220
}
}
return items;
}