违反了Big-O表示法中给定的平均时间复杂度

时间:2014-01-05 18:26:09

标签: java algorithm big-o

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

根据我的理解,Merge-sort的平均时间复杂度为O(N*log(N))但是在下面的代码中,我实际上使用了额外的for循环以及mergesort算法来删除重复项,这肯定违反了我的查找规则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);
    }
}

2 个答案:

答案 0 :(得分:1)

这里唯一的问题是你不明白如何进行时间分析。如果你有一个采用O(n)的例程和一个采用O(n * log(n))的例程,那么运行两个例程总共需要O(n * log(n))。因此,您的代码以您想要的方式运行在O(n * log(n))中。

为了正式做事,我们会注意到O()的定义如下:  f(x)∈O(g(x))当且仅当存在值c> 0和y使得f(x)<0。 cg(x)每当x&gt;收率

你的合并排序是在O(n * log(n))中,它告诉我们当n> 1时,它的运行时间被c1 * n * log(n)限制在上面。 y1表示某些c1,y1。你的复制消除是在O(n)中,它告诉我们当n> 1时,它的运行时间被c2 * n限制在上面。 y2表示某些c2和y2。使用这个,我们可以知道,当n> 1时,两者的总运行时间在c1 * n * log(n)+ c2 * n之上。 MAX(Y1,Y2)。我们知道c1 * n * log(n)+ c2 * n&lt; c1 * n * log(n)+ c2 * n * log(n)因为log(n)>当然,这简化为(c1 + c2)* n * log(n)。因此,当n> 1时,我们可以知道两者的运行时间在(c1 + c2)* n * log(n)之上。 max(y1,y2)因此,使用c1 + c2作为我们的c和max(y1,y2)作为y,我们知道两者的运行时间在O(n * log(n))。< / p>

非正式地,您可以知道快速增长的函数总是占主导地位,因此如果一段代码是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)。

答案 1 :(得分:0)

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

这是典型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]; 
   }

}