【问题标题】:Mergesort recurrence formulas - reconciling reality with textbooksMergesort 递推公式 - 用教科书调和现实
【发布时间】:2015-01-12 01:19:39
【问题描述】:

我认为这更像是编程而不是数学,所以我在这里发布。

我问题中的所有java算法都来自here

我们有一个迭代和递归的合并排序。两者都使用相同的合并功能。

教授this 讲座的教授说归并排序的关键操作是比较。

所以我根据比较想出了merge() 的这个公式:

>3n + 2

3:通过每个循环比较最坏情况。
n:循环将迭代的次数。
2:“测试”比较。

recursiveMergesort() 具有基本情况比较加上递归调用,总共:

>T(n/2) + 1 + 3n + 2 = T(n/2) + 3n + 3

iterativeMergesort() 只是有一个循环运行*n/2* 次和一个运行 n 次的嵌套循环。这让我想到了这个公式(但我认为这是错误的):

>(n/2) * n + 3n + 2 = (n^2)/2 + 3n + 2

书上说递归归并排序的递归公式是

2T(n/2) + theta(n)

用master方法解决

θ(NlogN)

问题 1: 我创建的公式如何简化为

T(n/2) + theta(n)

问题 2: 我可以使用这些公式中的任何一个(我创建的公式、教科书公式或时间复杂度*theta(nlogn)*)来预测运行此特定算法时的比较次数吗?数组大小 n

问题 3: 奖励:我的迭代方法公式是否正确?

合并:

private static void merge(int[] a, int[] aux, int lo, int mid, int hi) {
   // DK: add two tests to first verify "mid" and "hi" are in range
   if (mid >= a.length) return;
   if (hi > a.length) hi = a.length;
   int i = lo, j = mid;
   for (int k = lo; k < hi; k++) {
      if      (i == mid)     aux[k] = a[j++];
      else if (j == hi)      aux[k] = a[i++];
      else if (a[j] < a[i])  aux[k] = a[j++];
      else                   aux[k] = a[i++];
   }
   // copy back
   for (int k = lo; k < hi; k++)
      a[k] = aux[k];
}

递归合并排序:

public static void recursiveMergesort(int[] a, int[] aux, int lo, int hi) {
   // base case
   if (hi - lo <= 1) return;
   // sort each half, recursively
   int mid = lo + (hi - lo) / 2;
   recursiveMergesort(a, aux, lo, mid);
   recursiveMergesort(a, aux, mid, hi);
   // merge back together
   merge(a, aux, lo, mid, hi);
}

public static void recursiveMergesort(int[] a) {
    int n = a.length;
    int[] aux = new int[n];
    recursiveMergesort(a, aux, 0, n);
}

迭代归并排序:

public static void iterativeMergesort(int[] a) {
  int[] aux = new int[a.length];
  for (int blockSize=1; blockSize<a.length; blockSize*=2)
     for (int start=0; start<a.length; start+=2*blockSize)
        merge(a, aux, start, start+blockSize, start+2*blockSize);
   }

哇,你一路走到这里。谢谢!

【问题讨论】:

  • 书中对theta(N)的定义是什么?它与大 O 符号 O(n) 有什么不同吗?
  • 我认为当他说比较是关键部分时,他并不是指比较索引,索引总是整数。考虑一个对象数组,其compareTo() 方法必须访问它们的所有字段。关键比较是实际元素比较。
  • @NoseKnowsAll:是的。 theta(n) 包括下限和上限。 O(n) 只是上限。
  • @RealSkeptic:那么else if (a[j] &lt; a[i]) 是唯一的关键操作吗?掉期(aux[k] = a[j++])呢?它们很重要吗?

标签: algorithm big-o mergesort recurrence


【解决方案1】:

问题 1:

你从哪里得到你的事实?要获得您需要的theta(nlogn) 复杂度

T(n) = a T(n/b) + f(n), where a > 1, b > 1 and f(n) = cn + d. c != 0

注意:还有其他限制,由 Master theorem 规定

您不能从基于T(n) &gt; T(n/2) + 3n + 3 的递归关系派生。您可能忘记了大小为 n 的数组的成本是合并的成本加上 两倍 每个部分的成本。所以还是

  T(n) = 2T(n/2) + 3n + 3

问题 2:

在数组大小为 n 上运行此特定算法时,您不能使用 theta、Big O 或 Big Omega 来预测比较次数。因为它们是渐近表达式。你需要解决上面的关系,假设它是正确的。

例如T(n) = 2T(n/2) + 3n + 3 has the solution

T(n) = 3n log2(n) + 1/2(c+6)n - 3, c constant

这仍然是算法的比较次数。不考虑实际程序的所有优化和约束。

问题 3: 没有

【讨论】:

  • 我在弄清楚如何提问时确实忘记了 2。那么我如何从T(n) = 2T(n/2) + 3n + 32T(n/2) + theta(n) to use the master method? Is it simply that 3n + 2` 在 theta(n) 中?找出正确的迭代公式的好方法是什么。谢谢
  • 我想我在迭代中看到了我的错误。两个循环都增加了 2 * “blocksize”。因此它是相同的,2T(n/2)。
  • 3n + 2 在 theta(n) 中。查找 Knuth 定义时很容易证明
  • @MayNotBe 嗨。如果这个或任何答案已经解决了您的问题,请考虑通过单击复选标记接受它。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己提供了一些声誉。没有义务这样做
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 2016-07-15
  • 2010-11-03
  • 1970-01-01
  • 2017-04-21
  • 1970-01-01
相关资源
最近更新 更多