我想解决以下问题:给定n个元素的未排序数组,找到前k个最小元素。为此,我想构建一个大小为k的最大堆(来自数组的最后k个元素),然后扫描数组中的其余元素。如果我找到比我的根元素更小的元素,我交换两个元素然后我堆积我的堆。此解决方案应该在O(nlogk)时间和地点有效。但是我无法解决它(我有索引超出绑定的异常)。我试着调试它,但我不知道我的错误在哪里。这是我的代码:
public class KSmallest {
private static int[] a;
private static int n;
public static void buildheap(int []a){
n=a.length-1;
for(int i=n;i>=0;i--){
maxheap(a,i);
}
for (int i = n-1; i >= 0; i--) {
if(a[i]<a[start]){
exchange(i, 0);
maxheap(a, 0);
}
}
}
public static void exchange(int i, int j){
int t=a[i];
a[i]=a[j];
a[j]=t;
}
public static void sort(int []a0){
a=a0;
for(int i=n; i>0; i--){
exchange(0, i);
n=n-1;
maxheap(a, 0);
}
}
public static void main(String[] args) {
int []a1={4,1,3,2,7, 2, 1, 4};
int start = a1.length-k;
for(int i=start;i<a1.length;i++){
System.out.print(a1[i] + " ");
}
System.out.println();
//sort(a1);
for(int i=start;i<a1.length;i++){
System.out.print(a1[i] + " ");
}
}
}
我正在为此奋斗两天,所以我希望有人可以提供帮助。
答案 0 :(得分:1)
我知道这是一个学习练习,所以请随意忽略这个答案。但如果有人在现实世界中需要这样做,你就可以使用这个n * log(n)解决方案。
public static Collection<Integer> findKSmallest(Collection<Integer> data, int k) {
assert k > 0;
assert k <= data.size();
ArrayList<Integer> dataAsList = new ArrayList<Integer>(data);
Collections.sort(dataAsList);
return dataAsList.subList(0, k);
}
答案 1 :(得分:1)
首先要注意的是变量名称不是很有意义......'a','a0','i','j','k','n','t'以及作为可变的静态变量,它总是一个噩梦。
无论如何我运行了代码并在exchange()方法中得到了NullPointerException。
正在发生的事情是buildheap()方法有一个名为'a'的参数,它与用于类变量的名称相同,所以当它将'a'传递给maxheap()然后传递给while()时,它传递的是类变量而不是参数。
尝试将此行添加为buildheap()方法的第一行:
KSmallest.a = a;
修改强> 我不确定这是否真的有效,但它会阻止NPE。
对所有变量使用有意义的名称,就像你用'左',右'''最大'等一样,会有很大的帮助,一些额外的字符不会浪费树木!
同时尽量避免使用可变的静态变量。通过使用'final'关键字将它们保持为常量,并且 - 按惯例 - 使它们全部大写。或者使用实例变量来删除静态关键字,这就是更多的OOP范例。
无论如何祝你好运! :)
答案 2 :(得分:1)
编写堆数据结构是一种很好的做法。我正在使用优先级队列,这在Java中很容易获得最小堆。对于这个问题,我需要一个最大堆,所以我使用比较器来创建一个最大堆。
public class KLowestElements {
/*comparator to create max heap*/
static class MaxHeapComparator implements Comparator<Integer> {
@Override
public int compare(Integer a, Integer b) {
return b.compareTo(a);
}
}
public static void main(String[] args) {
//sample input
int[] input = { 11, 2, 23, 34, 5};
// heap size
int k = 3;
MaxHeapComparator maxHeapComparator = new MaxHeapComparator();
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(k,
maxHeapComparator);
//Loop Invariant: If heap size is k, compare top element with next
//element in the array. If element is smaller than the top element,
//remove the top integer and insert element from array.
for (int i = 0; i < input.length; i++) {
if (maxHeap.size() < k) {
maxHeap.add(input[i]);
} else if (maxHeap.peek() > input[i]) {
maxHeap.remove();
maxHeap.add(input[i]);
}
}
//print values
for (int i : maxHeap) {
System.out.print(i + " ");
}
}
}