我不想得到一个排序数组,只是第n个元素的值。例如,给定数组
a = [20, 5, 1, -3]
我希望能够查询
nth_element(a,2) = 1
在C ++中,有一个函数std::nth_element
可以做到这一点。是否有等效的Java函数?
谢谢!
答案 0 :(得分:5)
Java标准库不包含C ++ nth_element
算法的等效项。您最接近的将是使用Collections.sort
。
或者,您可以尝试实现自己的此功能版本。您可以通过执行标准排序并调用nth_element
来实现Collections.sort
,但根据您的时间要求,这可能会太慢。有许多用于执行此类重新排序的专用算法,称为选择算法,the Wikipedia page on the subject有几个很好的例子。根据经验,最快的算法称为quickselect,基于快速排序算法;它在预期的O(n)时间内运行,但对于病理学上不良的输入可以降级为O(n 2 )。有一种着名的(和众所周知的复杂)算法有时称为中位数算法,在最坏情况下运行O(n),但具有高常数因子,阻止它在实践中使用。
希望这有帮助!
答案 1 :(得分:0)
这是nth_element的Java实现:
class Nth_element
{
static void nth_element_helper2(double[] arr, int beg, int end)
{
for(int i = beg + 1; i < end; i++)
{
for(int j = i; j > beg; j--)
{
if(arr[j - 1] < arr[j])
break;
double t = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = t;
}
}
}
static void nth_element_helper(double[] arr, int beg, int end, int index)
{
if(beg + 4 >= end)
{
nth_element_helper2(arr, beg, end);
return;
}
int initial_beg = beg;
int initial_end = end;
// Pick a pivot (using the median of 3 technique)
double pivA = arr[beg];
double pivB = arr[(beg + end) / 2];
double pivC = arr[end - 1];
double pivot;
if(pivA < pivB)
{
if(pivB < pivC)
pivot = pivB;
else if(pivA < pivC)
pivot = pivC;
else
pivot = pivA;
}
else
{
if(pivA < pivC)
pivot = pivA;
else if(pivB < pivC)
pivot = pivC;
else
pivot = pivB;
}
// Divide the values about the pivot
while(true)
{
while(beg + 1 < end && arr[beg] < pivot)
beg++;
while(end > beg + 1 && arr[end - 1] > pivot)
end--;
if(beg + 1 >= end)
break;
// Swap values
double t = arr[beg];
arr[beg] = arr[end - 1];
arr[end - 1] = t;
beg++;
end--;
}
if(arr[beg] < pivot)
beg++;
// Recurse
if(beg == initial_beg || end == initial_end)
throw new RuntimeException("No progress. Bad pivot");
if(index < beg) // This is where we diverge from QuickSort. We only recurse on one of the two sides. This is what makes nth_element fast.
nth_element_helper(arr, initial_beg, beg, index);
else
nth_element_helper(arr, beg, initial_end, index);
}
static double nth_element(double[] arr, int index)
{
nth_element_helper(arr, 0, arr.length, index);
return arr[index];
}
public static void main(String[] args)
{
double[] arr = { 9, 7, 1, 5, 6, 4, 3, 2, 8, 0, 10 };
if(nth_element(arr, 5) == 5)
System.out.println("seems to work");
else
System.out.println("broken");
}
}
答案 2 :(得分:0)
Quickselect算法现已在AlgART库中实现: https://bitbucket.org/DanielAlievsky/algart/src/master/src/main/java/net/algart/arrays/ArraySelector.java 您可以通过Maven使用它,如下所述: http://algart.net/java/AlgART/
答案 3 :(得分:-1)
在Java中我认为你必须实现它,如下所示:
Integer nth_smallest_element(Integer[] originalArray, n) {
if (n >= originalArray.length)
throw new RuntimeException("Invalid index");
// Don't pass in your array, if you don't want it to be modified. Instead add them all later.
List<Integer> copyList = new ArrayList<Integer>();
copyList.addAll(originalArray);
Collections.sort(copyList);
return copyList.get(n);
}