在数组中查找K个最小元素Java

问题描述

我想在数组中找到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 语句也可能很简单,例如选择