问题描述
我想在数组中找到K个最小的元素,我基本上可以将数组排序为min-heap结构,但是我仍然得到错误的输出。
以下是我的输入内容:
arr = [9,4,7,1,-2,6,5]
k = 3
以下是代码:
class checkSmall {
public static int[] findKSmallest(int[] arr,int k) {
int[] result = new int[k];
int heapSize = arr.length;
// Write - Your - Code
for(int i = (heapSize - 1) / 2; i >= 0; i--)
{
minHeap(arr,i,heapSize);
}
for(int j = 0; j < k; j++)
{
result[j] = arr[j];
}
return result;
}
public static void minHeap(int[] arr,int index,int heapSize)
{
int smallest = index;
while(smallest < heapSize / 2)
{
int left = (2 * index) + 1; // 1 more than half the index
int right = (2 * index) + 2; // 2 more than half the index
if(left < heapSize && arr[left] < arr[index])
{
smallest = left;
}
if(right < heapSize && arr[right] < arr[smallest])
{
smallest = right;
}
if(smallest != index)
{
int temp = arr[index];
arr[index] = arr[smallest];
arr[smallest] = temp;
index = smallest;
}
else
{
break;
}
}
}
}
这是我的预期输出:
[-2,1,4]
尽管我的输出是:
[-2,5]
请我想知道我哪里出错了。
解决方法
构建minHeap之后,您必须提取元素并适当调整树。您只需按索引从数组中获取元素,而这不是堆的工作原理。
我对您的minHeap()
方法进行了少许修改,以使用recursion
,并且您应该检查arr[smallest] < arr[left]
而不是其他方式。
public static int[] findKSmallest(int[] arr,int k) {
int[] result = new int[k];
int heapSize = arr.length;
// Write - Your - Code
for(int i = (heapSize-1)/2; i >= 0; i--)
{
minHeap(arr,heapSize,i);
}
// extract elements from heap
for (int i=heapSize-1; i>0; i--)
{
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
minHeap(arr,i);
}
for(int j = 0; j < k; j++)
{
result[j] = arr[j];
}
return result;
}
public static void minHeap(int[] arr,int index,int heapSize)
{
int smallest = index;
int left = (2 * index) + 1; // 1 more than half the index
int right = (2 * index) + 2; // 2 more than half the index
if(left < heapSize && arr[smallest] < arr[left])
{
smallest = left;
}
if(right < heapSize && arr[smallest] < arr[right])
{
smallest = right;
}
if(smallest != index)
{
int temp = arr[index];
arr[index] = arr[smallest];
arr[smallest] = temp;
minHeap(arr,smallest,heapSize);
}
}
希望这会有所帮助。如预期的那样,结果是:
[-2,1,4]
,
您需要从根节点重新平衡堆。
chr1 111001 0 234 42 92 129
chr1 430229 0 267
chr2 22099 0 108 442
chr5 663800 0 311
,
自Java 8开始,我们就可以对流进行排序
替代代码:
Arrays.stream(arr).sorted().boxed().collect(Collectors.toList()).subList(0,k);
其中:
int[] arr = {9,4,7,-2,6,5};
int k = 3; // toIndex
上下文和测试平台中的替代代码:
public static void main(String[] args) {
int[] arr = {9,5};
int k = 3; // toIndex
List<Integer> listResult = Arrays.stream(arr).sorted().boxed().collect(Collectors.toList()).subList(0,k);
// print out list result
System.out.println("Output of list result: " + listResult);
int[] arrayResult = listResult.stream().mapToInt(i->i).toArray();
// print out array result
List<String> arrayResultAsString =
Arrays.stream(arrayResult).boxed().map(i -> String.valueOf(i)).collect(Collectors.toList());
System.out.println("Output of array result: " + arrayResultAsString);
}
输出:
Output of list result: [-2,4]
Output of array result: [-2,4]
,
您可以使用 Arrays.stream(int[])
方法:
int[] arr = {9,5};
int k = 3;
int[] minHeap = Arrays.stream(arr).sorted().limit(k).toArray();
System.out.println(Arrays.toString(minHeap)); // [-2,4]
,
如果 K 相对于数组大小而言相对较小,我的建议是使用选择排序,因此它可能是一种设计模式策略 - 取决于 K 与数组大小的关系,例如两个过程:小 K 的选择排序和快速排序巨大的 K。除了使用设计模式,好的 if 语句也可能很简单,例如选择