【问题标题】:modifying mergesort to count inversions in JavaScript修改合并排序以计算 JavaScript 中的倒数
【发布时间】:2014-11-25 16:07:08
【问题描述】:

我的问题是有没有更好的方法来优化下面的代码?每次合并数组时,inversions 会重置并递增,并且在 2 个排序数组(左半边和右半边)的最终合并中,我们得到 inversions 的最终值。在没有全局变量的情况下,有没有更好/更清洁的做事方式?谢谢!

var inversions = 0;
  function mergeSortedArray(a, b){
    var merged = [], 
        aElm = a[0],
        bElm = b[0],
        i = 1,
        j = 1,
        inversions = 0;
    while(aElm || bElm){
     if((aElm && !bElm) || aElm < bElm){
       merged.push(aElm);
       aElm = a[i++];
     }   
     else {
       merged.push(bElm);
       bElm = b[j++];
       inversions++;
     }
    }
    return merged;
  }

  function mergeSort(items){


      if (items.length < 2) {
          return items;
      }

      var middle = Math.floor(items.length / 2),
          left    = items.slice(0, middle),
          right   = items.slice(middle);

      return mergeSortedArray(mergeSort(left), mergeSort(right));
  }

【问题讨论】:

  • 您需要inversions 做什么?它是什么意思?我不明白它应该做什么,显然合并排序算法不需要它。
  • @Bergi 当x &gt; yx 出现在数组中的y 之前时,会发生反转。这是计算数组中反转次数的标准高效算法。
  • 啊,en.wikipedia.org/wiki/Inversion_(discrete_mathematics) 的链接可能会有所帮助 :-)
  • 为什么不简单地传递一个变量并合并它们,即在回溯步骤中将它们加在一起? :)

标签: javascript algorithm mergesort


【解决方案1】:

优化往往是丑陋的。 :-)

我看到的主要性能问题是有很多创建数据被当作垃圾丢弃。为了解决这个问题,你可以做的是有一个输入数组和一个输出数组。您将两个数组以及两个块要合并的位置的索引传递给您的合并函数。返回反转次数。在归并排序的每一级,输入和输出数组的角色互换。

代码会很挑剔、棘手且难以阅读。但应该表现更好。

至于全局,在代码中处理它的“理论上正确”的方法是返回一个包含数组和计数的数据结构。然而,下一个最好的(在我看来是首选的)方法是在通过全局通信的函数周围放置一个块。在mergeSort 中初始化它,在mergeSortedArray 中使用它并将该例程重命名为_mergeSortedArray 以表明它是私有的,不应调用。这将保持可读性,同时保证正确使用现在更好的本地化全局。

【讨论】:

    猜你喜欢
    • 2014-12-10
    • 1970-01-01
    • 2015-07-08
    • 1970-01-01
    • 2012-12-27
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    • 2018-05-30
    相关资源
    最近更新 更多