【发布时间】: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)