【问题标题】:Trying to understand complexity of quick sort试图理解快速排序的复杂性
【发布时间】:2016-10-28 05:21:50
【问题描述】:

我知道当枢轴是最小或最大元素时会发生最坏的情况。然后其中一个分区是空的,我们对 N-1 个元素重复递归

但是如何计算到O(N^2)

我看了几篇文章还是没能完全理解。

同样,最好的情况是当枢轴是数组的中位数并且左右部分的大小相同时。但是,那么O(NlogN) 的值是如何计算出来的

【问题讨论】:

    标签: java arrays algorithm sorting quicksort


    【解决方案1】:

    我知道当枢轴是最小或最大元素时会发生最坏的情况。然后其中一个分区为空,我们对 N-1 个元素重复递归。

    因此,假设您反复选择最差的支点;即在 N-1 的情况下,一个分区是空的,然后你用 N-2 个元素递归,然后是 N-3,依此类推,直到你到达 1。

    N-1 + N-2 + ... + 1 的总和是(N * (N - 1)) / 2。 (现在学生通常在高中数学中学习这个......)

    O(N(N-1)/2)O(N^2) 相同。您可以从 Big-O 表示法的数学定义的第一原理中推断出这一点。


    同样,最好的情况是当枢轴是数组的中位数并且左右部分的大小相同时。但是,那么如何计算 O(NlogN) 的值。

    这有点复杂。

    把问题想象成一棵树:

    • 在顶层,您将问题拆分为两个大小相等的子问题,并将 N 个对象移动到正确的分区中。

    • 在第 2 级。您将两个子问题拆分为四个子子问题,并在 2 个问题中将 N/2 个对象移动到正确的分区中,总共移动了 N 个对象。

    • 在底层,您有 N/2 个大小为 2 的子问题,您(理论上)将其拆分为 N 个大小为 1 的问题,再次复制 N 个对象。

    很明显,在每个级别你移动 N 个对象。对于大小为 N 的问题,树的高度是 log2N。所以...有 N * log2N 个对象移动;即 O(N * log2)

    但是 log2N 是 logeN * loge2。 (又是高中数学。)

    所以 O(Nlog2N) 是 O(NlogN)

    【讨论】:

      【解决方案2】:

      对您的陈述稍作更正:

      我知道当枢轴是最小或最大元素时会发生最坏的情况。

      实际上,最坏的情况发生在每个连续的枢轴是剩余分区数组的最小或最大元素。

      为了更好地理解最坏的情况:考虑一个已经排序的数组,您可能正在尝试对其进行排序。

      您选择第一个元素作为第一个枢轴。比较数组的其余部分后,您会发现 n-1 元素 仍然 在另一端(右侧),第一个元素保持在同一位置,实际上完全击败了 分区的目的。您将一直重复这些步骤,直到最后一个元素具有相同的效果,这反过来又会解释(n-1 + n-2 + n-3 + ... + 1) 比较,并且总和为(n*(n-1))/2 比较。所以,

      O(n*(n-1)/2) = O(n^2) for worst case.
      

      为了克服这个问题,始终建议随机拾取每个连续的枢轴。

      我也会尝试为一般情况添加解释。

      【讨论】:

        【解决方案3】:

        最好的情况可以从大师定理推导出来。例如,请参阅 https://en.wikipedia.org/wiki/Master_theorem,或 Cormen、Leiserson、Rivest 和 Stein:算法简介,了解定理的证明。

        【讨论】:

          【解决方案4】:

          一种思考方式如下。

          如果快速排序对枢轴的选择不佳,则枢轴会导致不平衡的分区,大多数元素位于枢轴的一侧(下方或上方)。在极端情况下,您可以按照您的建议,所有元素都低于或高于枢轴。在这种情况下,我们可以使用递归T(n)=T(1)+T(n-1)+O(n) 对快速排序的时间复杂度进行建模。但是,T(1)=O(1),我们可以写出重复出现的T(n)=O(n)+O(n-1)+...+O(1) = O(n^2)。 (必须注意理解对 Big-Oh 项求和的含义。)

          另一方面,如果快速排序反复做出良好的枢轴选择,那么这些枢轴会导致平衡分区。在最好的情况下,大约一半的元素将在枢轴下方,大约一半的元素将在枢轴上方。这意味着我们在两个大小大致相等的子数组上进行递归。然后重复变为T(n)=T(n/2)+T(n/2)+O(n) = 2T(n/2)+O(n)。 (在这里,如果想要正式一点,也必须注意对 n/2 进行四舍五入。)这解决了 T(n)=O(n log n)

          最后一段的直觉是,我们以排序顺序计算枢轴的相对位置,而不实际对整个数组进行排序。然后我们可以计算下面子数组中枢轴的相对位置,而不必担心上面子数组中的元素;对于上面的子数组也是如此。

          【讨论】:

            【解决方案5】:

            首先,在这里粘贴一个伪代码:

            在我看来,你需要了解两种情况:最坏情况和最好情况。

            • 最坏的情况: 当枢轴将列表分成大小为 0 和 n-1 的两个子列表时,会出现最不平衡的分区。递归的复杂度是T(n)=O(n)+T(0)+T(n-1)=O(n)+T(n-1)。 主定理告诉我们 T(n)=O(n²)。
            • 最好的情况: 在最平衡的情况下,每次执行分区时,我们都会将列表分成几乎相等的两个部分。和最坏的一样,递归关系是T(n)=O(n)+2T(n/2)。并且可以转化为 T(n)=O(n logn)。

            【讨论】:

              猜你喜欢
              • 2017-11-20
              • 2018-10-16
              • 1970-01-01
              • 1970-01-01
              • 2013-04-26
              • 1970-01-01
              • 2012-07-06
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多