【问题标题】:How do I write a sort worse than O(n!)我怎么写比 O(n!)
【发布时间】:2010-09-06 17:39:54
【问题描述】:

我为我的娱乐编写了一个 O(n!) 排序,如果不完全替换它,就无法简单地优化它以更快地运行。 [不,我不只是在物品被分类之前随机化这些物品]。

我如何编写一个更糟糕的 Big-O 排序,而不只是添加可以被拉出以降低时间复杂度的无关垃圾?

http://en.wikipedia.org/wiki/Big_O_notation 具有按增长顺序排序的各种时间复杂度。

编辑:我找到了代码,这是我的 O(n!) 确定性排序,带有有趣的 hack 以生成列表的所有组合的列表。我有一个稍微长一点的 get_all_combinations 版本,它返回一个可迭代的组合,但不幸的是我不能让它成为一个单一的语句。 [希望我没有通过修复错别字和删除以下代码中的下划线来引入错误]

def mysort(somelist):
    for permutation in get_all_permutations(somelist):
        if is_sorted(permutation):
            return permutation

def is_sorted(somelist):
    # note: this could be merged into return... something like return len(foo) <= 1 or reduce(barf)
    if (len(somelist) <= 1): return True
    return 1 > reduce(lambda x,y: max(x,y),map(cmp, somelist[:-1], somelist[1:]))

def get_all_permutations(lst):
    return [[itm] + cbo for idx, itm in enumerate(lst) for cbo in get_all_permutations(lst[:idx] + lst[idx+1:])] or [lst]

【问题讨论】:

    标签: sorting big-o


    【解决方案1】:

    有一个(经过验证的!)最差排序算法,称为 slow sort,它使用“乘法并降”范式并在指数时间内运行。

    虽然您的算法速度较慢,但​​它的进展并不稳定,而是执行随机跳跃。此外,慢排序的最佳情况仍然是指数的,而您的情况是恒定的。

    【讨论】:

      【解决方案2】:

      Chris 和我在different question. 中提到了BozosortBogosort

      【讨论】:

        【解决方案3】:

        总是有NeverSort,即O(∞):

        def never_sort(array)
          while(true)
          end
          return quicksort(array)
        end
        

        PS:我真的很想看看你的确定性 O(n!) 排序;我想不出任何 O(n!),但在经典计算中有一个有限的上限(也就是确定性的)。

        PPS:如果您担心编译器会清除该空的 while 块,您可以通过在块内外使用变量来强制它不要:

        def never_sort(array)
          i=0
          while(true) { i += 1 }
          puts "done with loop after #{i} iterations!"
          return quicksort(array)
        end
        

        【讨论】:

          【解决方案4】:

          您总是可以进行随机排序。它的工作原理是随机重新排列所有元素,然后检查它是否已排序。如果没有,它会随机使用它们。我不知道它如何适合大 O 表示法,但它肯定会很慢!

          【讨论】:

            【解决方案5】:

            这是您可以获得的最慢的有限排序:

            将 Quicksort 的每个操作链接到 Busy Beaver 函数。

            当您获得 >4 次操作时,您将需要向上箭头符号 :)

            【讨论】:

              【解决方案6】:

              我能想到的一种方法是通过一个函数计算每个元素的发布位置,该函数逐渐将大元素移到末尾,将小元素移到开头。如果您使用基于 trig 的函数,则可以使元素在列表中密切接触,而不是直接朝向它们的最终位置。处理完集合中的每个元素后,再进行一次全遍历以确定数组是否已排序。

              我不确定这会给你 O(n!),但它应该仍然很慢。

              【讨论】:

                【解决方案7】:

                我认为,如果您进行大量复制,那么您可以获得“合理”的蛮力搜索(N!),每个案例需要 N^2 次,给出 N!*N^2

                【讨论】:

                  【解决方案8】:

                  循环遍历所有包含 n 个整数的数组 t 怎么样(整数的 n 元组是可数的,所以这是可行的,尽管它当然是一个无限循环),并且对于其中的每一个:

                  • 如果它的元素与输入数组的元素完全相同(参见下面的算法!)并且数组已排序(例如线性算法,但我相信我们可以做得更糟),然后返回 t;
                  • 否则继续循环。

                  要检查两个长度为 n 的数组 a 和 b 是否包含相同的元素,请使用以下递归算法:遍历 0 和 n-1 之间的所有索引对 (i,j),并针对每个这样的对

                  • 测试是否 a[i]==b[j]:
                  • 如果是这样,当且仅当对通过从 a 中删除 a[i] 和从 b 中删除 b[j] 获得的列表进行递归调用返回 TRUE;
                  • 继续循环遍历情侣,如果所有情侣都完成,则返回 FALSE。

                  时间很大程度上取决于输入数组中整数的分布。

                  说真的,这样的问题有什么意义吗?

                  编辑:

                  @Jon,你的随机排序平均会在 O(n!) 中(因为有 n! 个排列,你有 1/n! 的概率找到正确的排列)。这适用于不同整数的数组,如果某些元素在输入数组中多次出现,可能会略有不同,然后取决于输入数组元素的分布(在整数中)。

                  【讨论】:

                    猜你喜欢
                    • 2019-10-23
                    • 1970-01-01
                    • 2014-11-29
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-11-05
                    • 2018-10-24
                    • 2023-03-25
                    • 2020-11-29
                    相关资源
                    最近更新 更多