【问题标题】:O(nlogn) Runningtime ApproachO(nlogn) 运行时间方法
【发布时间】:2015-03-17 02:22:31
【问题描述】:

该函数使用一个 int 列表并按升序生成列表中的唯一元素。例如:

    singles([4,1,4,17,1]) => [1,4,17]

我只能在 O(n^2) 运行时间内做到这一点,想知道如何在没有循环的情况下更改为 O(n) 运行时间。

      def singles(lst):
        if lst==[]: return []
        else:
        rest_fn = list (filter (lambda x: x!=lst[0], lst[1:]))
        return [lst[0]] + singles(rest_fn)

【问题讨论】:

  • 对列表进行排序,只获取唯一的项目。
  • 排序列表....那么现在几点了?
  • 涵盖排序和设置的更好链接:wiki.python.org/moin/TimeComplexity(排序列表是 O(nlogn),如果我在行之间正确阅读,从列表创建集合是 O(n)
  • @Dogweather 好点(尽管我认为输出整个集合仍然是 O(N) (O(1) 来检索每个元素),除非我遗漏了什么),而且,我认为做一个有序集(我看到的任何一个性能链接中都没有列出)需要 O(log N) 来插入每个元素,使创建仍然是 O(N log N)...你'只是让它成为初始化部分的一部分,这是一种完全有效的方法
  • @Foon 好问题——我已经有一段时间没有研究插入的复杂性了。关于。输出为 O(1),afaik 我们通常测量“比较”(在排序中)以确定复杂性。因此,如果您的 ADT 已经预排序和预过滤,则无需进行比较。因此 O(1)。当然,现实世界的需求可能决定更高的前期成本是完全可以接受的。例如,在并行过程中插入的项目,或者只是偶尔插入。

标签: python python-3.x


【解决方案1】:

如上所述,根据https://wiki.python.org/moin/TimeComplexity(引用自Time complexity of python set operations?,它还链接到更详细的操作列表,排序应该有时间复杂度O(nlogn)。集合应该有时间复杂度O(n)。所以,做sorted(set(input))的时间复杂度应该是O(n) + O(nlogn) = O(nlogn)

编辑: 如果你不能使用 set,你应该提一下,但作为一个提示,假设你可以使用 sorted,如果你使用双端队列(它的 O(1) 最差,你仍然可以在 O(n) 中提取唯一性案例插入)。类似的东西

rez = deque()
last = None
for val in sorted(input):
   if val != last:
      rez.add(val) # or whatever deque uses to add to the end of the list
      last = val

【讨论】:

  • 但是如果不能在fn中使用set呢?
  • 我有点迷茫,能不能帮我看看我的做法,改成O(n)?
  • 不能改为O(n)。只有部分的答案可以是O(n)。
  • 你能给我一个在没有设置和循环的情况下实现 O(n) 的方法吗? @Dogweather
  • 谢谢@Dogweather。需要明确的是:由于信息论的原因,基本上 O(n log(n)) 是基于比较的排序的限制(请参阅上面我对 TimSort 的评论中的 wiki 链接)。 RadixSort(en.wikipedia.org/wiki/Radix_sort,见效率),如果你正确地看待它可以被认为是 O(n) 但这取决于某些假设,我没有信心试图解释它们,在实践中,它更多 O(k *n) 其中 k 最终与 log N 非常相似。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-04
  • 1970-01-01
  • 2018-12-30
  • 2019-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多