【问题标题】:violating the given average time complexity in Big-O notation违反 Big-O 表示法中给定的平均时间复杂度
【发布时间】:2014-01-05 18:26:09
【问题描述】:

我正在尝试实施一种解决方案,以在给定整数列表中找到第 k 个最大元素,其中重复项具有 O(N*log(N)) Big-O 表示法的平均时间复杂度,其中 N 是列表中的元素数。

根据我的理解,合并排序的平均时间复杂度为O(N*log(N)),但是在我下面的代码中,我实际上使用了一个额外的 for 循环以及合并排序算法来删除重复项,这绝对违反了我的第 k 个查找规则O(N*log(N)) 的最大元素。如何以 Big-O 表示法实现我的任务 O(N*log(N)) 平均时间复杂度?

public class FindLargest {
    public static void nthLargeNumber(int[] arr, String nthElement) {
        mergeSort_srt(arr, 0, arr.length - 1);
        // remove duplicate elements logic
        int b = 0;
        for (int i = 1; i < arr.length; i++) {
            if (arr[b] != arr[i]) {
                b++;
                arr[b] = arr[i];
            }
        }

        int bbb = Integer.parseInt(nthElement) - 1;
        // printing second highest number among given list
        System.out.println("Second highest number is::" + arr[b - bbb]);
    }

    public static void mergeSort_srt(int array[], int lo, int n) {
        int low = lo;
        int high = n;
        if (low >= high) {
            return;
        }

        int middle = (low + high) / 2;
        mergeSort_srt(array, low, middle);
        mergeSort_srt(array, middle + 1, high);
        int end_low = middle;
        int start_high = middle + 1;
        while ((lo <= end_low) && (start_high <= high)) {
            if (array[low] < array[start_high]) {
                low++;
            } else {
                int Temp = array[start_high];
                for (int k = start_high - 1; k >= low; k--) {
                    array[k + 1] = array[k];
                }
                array[low] = Temp;
                low++;
                end_low++;
                start_high++;
            }
        }
    }

    public static void main(String... str) {
        String nthElement = "2";
        int[] intArray = { 1, 9, 5, 7, 2, 5 };

        FindLargest.nthLargeNumber(intArray, nthElement);
    }
}

【问题讨论】:

  • 如果你想要 N 个项目中最大的 N 个,听起来你想要最小的。为什么不遍历列表,跟踪当前最小值。当您在 O(N) 时间内到达终点时,您将拥有最小值。您是指 N 个项目中第 k 个最大的吗?
  • 你的问题有点混乱。在 O(n log n) 中不可能找到第 n 个最大的元素。考虑一个包含 1000 万个元素的列表,并且您想要第 4 个最大的元素。你是说你的算法的运行时间应该由 4 来管理,而不是 1000 万。您可能是指长度为 n 的列表中的第 k 个最大元素。现在进行排序,这需要 O(n log n)。再一次寻找第 k 个最大的只有 O(n),所以总体运行时间仍然是 O(n log n)。然后请注意,您可以根据@OliCharlesworth 的建议将其减少到 O(n)。
  • 我的错,我的意思是我刚刚更新了我的问题的第 k 个最大元素
  • 除此之外:归并排序(如果实施正确)保证 O(n log n) (这是最坏的情况,也是平均情况)。再次遍历您的列表,不会改变整体复杂性,因为:O(n + n log n) = O(n log n)

标签: java algorithm big-o


【解决方案1】:

您唯一的问题是您不了解如何进行时间分析。如果你有一个需要 O(n) 的例程和一个需要 O(n*log(n)) 的例程,那么运行这两个例程总共需要 O(n*log(n))。因此,您的代码可以按照您的意愿在 O(n*log(n)) 中运行。

要正式地做事情,我们会注意到 O() 的定义如下: f(x) ∈ O(g(x)) 当且仅当存在值 c > 0 和 y 使得当 x > y 时 f(x)

您的合并排序在 O(n*log(n)) 中,这告诉我们当 n > y1 对于某些 c1,y1 时,它的运行时间以 c1*n*log(n) 为界。您的重复消除在 O(n) 中,它告诉我们当某些 c2 和 y2 的 n > y2 时,它的运行时间以 c2*n 为界。使用这个,我们可以知道,当 n > max(y1,y2) 时,两者的总运行时间以 c1*n*log(n)+c2*n 为界。我们知道 c1*n*log(n)+c2*n 1,这当然简化为 (c1 +c2)*n*log(n)。因此,我们可以知道,当 n > max(y1,y2) 时,两者的运行时间以 (c1+c2)*n*log(n) 为界,因此,使用 c1+c2 作为我们的 c 和 max (y1,y2) 作为我们的y,我们知道两者加起来的运行时间是O(n*log(n))。

非正式地,你可以知道快速增长的函数总是占主导地位,所以如果一段代码是 O(n),第二段是 O(n^2),那么组合就是 O(n^2)。如果一个是 O(log(n)),第二个是 O(n),则组合是 O(n)。如果一个是 O(n^20),第二个是 O(n^19.99),则组合是 O(n^20)。如果一个是O(n^2000),第二个是O(2^n),那么组合是O(2^n)。

【讨论】:

  • 感谢您提供帮助的解释......另外,如果我必须实施相同的算法来找到平均时间复杂度 O(N) 的第 k 个最大元素,我应该使用哪种算法用于在java中编码?我在看冒泡排序,但它的平均时间复杂度为 O(n2)
  • 你可能应该看看上面的 cmets,因为有人已经链接到关于选择算法的维基百科文章,它告诉你一个 O(N) 选择算法。
【解决方案2】:

这里的问题是您的合并例程,您使用了另一个循环,我不明白为什么,因此我会说您的合并算法 O(n^2) 将您的合并排序时间更改为 O(n^2)。

这是典型的 O(N) 合并例程的伪代码:-

void merge(int low,int high,int arr[]) {


  int buff[high-low+1];
  int i = low;
  int mid = (low+high)/2;
  int j = mid +1;
  int k = 0;
  while(i<=mid && j<=high) {

      if(arr[i]<arr[j]) {
           buff[k++] = arr[i];
           i++;
      }
      else {
           buff[k++] = arr[j];
           j++;
      }
  }

  while(i<=mid) {
        buff[k++] = arr[i];
           i++;       
  }

    while(j<=high) {
        buff[k++] = arr[j];
           j++;       
  }


  for(int x=0;x<k;x++) {

       arr[low+x] = buff[x]; 
   }

}

【讨论】:

    猜你喜欢
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-30
    • 1970-01-01
    • 1970-01-01
    • 2019-04-27
    • 1970-01-01
    相关资源
    最近更新 更多