方法需要返回k个元素a [i],使得ABS(a [i] - val)是k个最大的评估。我的代码仅适用于大于val的整数。如果整数小于val,它将失败。我可以在不导入除java.util.Arrays之外的任何内容的情况下执行此操作吗?有人可以开导我吗?任何帮助将不胜感激!
public static int[] farthestK(int[] a, int val, int k) {// This line should not change
int[] b = new int[a.length];
for (int i = 0; i < b.length; i++) {
b[i] = Math.abs(a[i] - val);
}
Arrays.sort(b);
int[] c = new int[k];
int w = 0;
for (int i = b.length-1; i > b.length-k-1; i--) {
c[w] = b[i] + val;
w++;
}
return c;
}
测试用例:
@Test public void farthestKTest() {
int[] a = {-2, 4, -6, 7, 8, 13, 15};
int[] expected = {15, -6, 13, -2};
int[] actual = Selector.farthestK(a, 4, 4);
Assert.assertArrayEquals(expected, actual);
}
There was 1 failure:
1) farthestKTest(SelectorTest)
arrays first differed at element [1]; expected:<-6> but was:<14>
FAILURES!!!
Tests run: 1, Failures: 1
答案 0 :(得分:3)
前k问题可以通过多种方式解决。在您的情况下,您添加一个新参数,但它确实无关紧要。
第一个也是最简单的一个:只需对数组进行排序。时间复杂度:O(nlogn)
public static int[] farthestK(Integer[] a, final int val, int k) {
Arrays.sort(a, new java.util.Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return -Math.abs(o1 - val) + Math.abs(o2 - val);
}
});
int[] c = new int[k];
for (int i = 0; i < k; i++) {
c[i] = a[i];
}
return c;
}
第二种方式:使用堆来保存最大k值,时间复杂度:O(nlogk)
/**
* Use a min heap to save the max k values. Time complexity: O(nlogk)
*/
public static int[] farthestKWithHeap(Integer[] a, final int val, int k) {
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(4,
new java.util.Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Math.abs(o1 - val) - Math.abs(o2 - val);
}
});
for (int i : a) {
minHeap.add(i);
if (minHeap.size() > k) {
minHeap.poll();
}
}
int[] c = new int[k];
for (int i = 0; i < k; i++) {
c[i] = minHeap.poll();
}
return c;
}
第三种方式:分而治之,就像快速排序一样。将数组划分为两部分,并在其中一部分中找到第k个。时间复杂度:O(n + klogk) 代码有点长,所以我只提供链接。
答案 1 :(得分:2)
对阵列进行排序将花费您 O(n log n)时间。你可以使用k-selection在 O(n)时间内完成。
时间复杂度:#1的O(n)时间,#2的O(n)时间和#3的O(k)时间=&gt;总时间复杂度为O(n)
。 (Quickselect在O(n)预期时间内运行,并且存在复杂的最坏情况线性时间选择算法。)
空间复杂度:O(n)
。
伪代码:
farthest_from(k, val, A):
let n = A.length
# Compute B. Elements are objects to
# keep track of the original element in A.
let B = array[0 .. n - 1]
for i between 0 and n - 1:
B[i] = {
value: abs(A[i] - val)
index: i
}
# k_selection should know to compare
# elements in B by their "value";
# e.g., each B[i] could be java.lang.Comparable.
k_selection(n - k - 1, B)
# Use the top elements in B to link back to A.
# Return the result.
let C = array[0 .. k - 1]
for i between 0 and k - 1:
C[i] = A[B[n - k + i].index]
return C
答案 2 :(得分:0)
您可以稍微修改此算法,并根据您的要求使用它来打印k个元素。(这是您需要对此算法中的一些更改进行的唯一工作。)
探索此链接。 http://jakharmania.blogspot.in/2013/08/selection-of-kth-largest-element-java.html
此算法使用选择排序 - 因此输出将是基于对数时间复杂度的答案,非常有效。
答案 3 :(得分:0)
O(n)
算法,来自partial sorting上的维基百科条目:
使用线性时间median-of-medians selection algorithm找到第k个最小元素。然后进行线性传递以选择小于第k个最小元素的元素。
这种情况下的集合是通过获取原始数组,减去给定值,取绝对值(然后将其否定以使最大值变为最小值)来创建的。