【问题标题】:Can anyone tell me the Big O time of my sort algorithm?谁能告诉我排序算法的大 O 时间?
【发布时间】:2025-02-28 22:55:01
【问题描述】:

我不太擅长记住所有不同的算法,所以我实现了一个,但我不确定如何计算它的大 O 时间,因为有一个移动指针。

这不是很有效,或者至少有更好的排序。

它通过来回移动一个指针来对数组进行排序,从位置 0 开始向右移动,每次交换时返回一次,以便查看左侧的元素是否需要也变了。

代码如下:

function countInversions(arr) {
  var count = 0;
  var i=0;

  while(i < arr.length) {
    // look behind
    if (i-1 >= 0 && arr[i-1] > arr[i]) {
      swap(arr, i, i-1);
      count++;
      i--;
      continue;
    }    
    // look ahead
    else if (arr[i] > arr[i+1]) { 
      swap(arr, i, i+1);
      count++;
      continue;
    }

    i++;
  }

  return count;
}

function swap(arr, i1, i2) {
  const temp = arr[i2];
  arr[i2] = arr[i1];
  arr[i1] = temp;
}

编辑:它看起来像“冒泡排序”。我仍然不确定大o是什么。

【问题讨论】:

  • 指针与否,你实现了冒泡排序,对吧?冒泡排序(除非已经排序)通常是 O(n^2)
  • 是的,这是冒泡排序,您只需同时进行 2 次迭代。你仍然有 O(n^2),最坏的情况是最大或最小元素靠近中间。
  • 是的,你是对的!多谢你们。 @gview

标签: sorting big-o


【解决方案1】:

您的排序确实是冒泡排序,但只是将小项目移到第一个,而不是将大项目移到最后一个。

对于排序算法,复杂性通常被认为是最差、最好和平均的情况。您的实现(冒泡排序)中最好的情况是当数组已经排序并且复杂度为 O(n) 时。 但最差和平均是 O(n^2)

顺便说一句,我注意到您已经计算了交换操作的数量,只是想提一下,您应该根据大 O 计算来考虑循环的数量。然而,这完全取决于您的平台和要求,例如,如果扫描一个数组几乎不需要时间,但在您的平台上交换项目会花费更多时间,那么计算交换是有意义的。

我还想建议对您的算法进行一些改进:

在将项目向左移动之前,您可以保存当前位置,一旦它安顿下来,只需向后移动并从之前的位置继续。请参阅下面的修改代码。

无论如何,时间复杂度不会改变,它仍然是 O(n^2),但它会给你一点点改进。

function countInversions(arr) {
  var count = 0;
  var i=0;
  var old_i=-1;

  while(i < arr.length) {
    count++;
    // look behind
    if (i-1 >= 0 && arr[i-1] > arr[i]) {
      swap(arr, i, i-1);
      if (old_i<0)
        old_i=i;
      i--;
      continue;
    }    
    // look ahead
    else if (arr[i] > arr[i+1]) { 
      swap(arr, i, i+1);
      continue;
    }

    if (old_i>0){
      i=old_i;
      old_i=-1;
    }
    i++;
  }
  return count;
}

function swap(arr, i1, i2) {
  const temp = arr[i2];
  arr[i2] = arr[i1];
  arr[i1] = temp;
}

【讨论】: