【发布时间】:2012-06-21 00:21:21
【问题描述】:
我正在用我的 O(n*log(n)) 解决方案展示我的教授在课堂上展示的一个问题:
给定n 号码列表,我们希望执行以下n-1 次:
- 从列表中提取两个最小元素
x,y并呈现出来 - 创建一个新号码
z,其中z = x+y - 把
z放回列表中
建议O(n*log(n)) 和O(n) 的数据结构和算法
解决方案:
我们将使用最小堆:
只创建一次堆需要 O(n)。之后,提取两个最小元素将花费 O(log(n))。将z 放入堆中需要 O(log(n))。
执行上述n-1 次需要 O(n*log(n)),因为:
O(n)+O(n∙(logn+logn ))=O(n)+O(n∙logn )=O(n∙logn )
但是我怎么能在 O(n) 中做到呢?
编辑:
通过说:“从列表中提取两个最小元素x,y 并呈现它们”,我的意思是printf("%d,%d" , x,y),其中x 和y 是列表中的最小元素当前列表。
【问题讨论】:
-
只是为了确保清楚:您想将数组简化为单个元素,每一步都删除 2 个最小元素并注入它们的总和,并且您希望在 O(n) 中执行此操作时间?
-
你知道列表中数字的大小吗?它们是否保证在某个范围内?
-
您不可能误解了这个问题,是吗? :) 我下意识的反应是说这是不可能的。显然,您需要迭代数组 (n-1) 次,这意味着您将在 O(n) 次的范围内执行 some 操作。要实现总体 O(n) 时间,您需要该操作为 O(1)。您可以在 O(1) 时间内在排序列表中找到两个最小值,但将一个值注入列表并保持排序将是 log(n)。除非你想进入基数排序,但这有点可疑。
-
+1 对于这个问题,我的好奇心被激起了。 :)
-
Cheeken 下意识反应的证明:假设你能做到这一点。进一步假设当您将
z插入到列表中时,您在其上粘贴了一个标志,表示“这是一个计算值,而不是原始值”。最后假设当你显示数字时,你只打印出未设置标志的数字。然后你已经在O(n)中对你的数字列表进行了排序。因此,需要某种欺骗手段,例如对固定大小的整数进行基数排序。
标签: arrays algorithm list math data-structures