最大堆找到第k个最小元素

时间:2018-11-08 08:13:02

标签: java arrays algorithm sorting heap

任务:

  

您有一个未排序的元素列表(在我们的情况下为整数),并且必须在该列表中找到第k个最小的元素。当然,显而易见的想法是按升序对列表进行排序并返回第k个最小元素。这应该在O(N Log N)中完成。

我正在尝试找到使用最大堆的第k个最小元素。据我了解,我需要对Array进行升序排序,并在得到第k个最小元素时返回。如果我正确理解,最好使用最大堆对数组进行升序排序,但是最好使用最小堆来查找第k个最小元素。这是不明白的地方。如何将数组按升序排序并返回第k分钟?我在查找如何使用最大堆的情况下获取第k个最小元素时遇到问题,因为等到数组完全排序后再进行for循环遍历并使其第k个最小就没有意义了。不会使HeapSort O(N log N),因为它将需要另一个for循环来遍历Array。如果我使用Min堆,那将是降序。

Max Heap以这种方式对数组进行升序排序:

  

产生最大堆:[10,9,8,5,1,8,3,5,5,1]

     

[9,5,8,5,1,8,3,1,5,10]

     

[8、5、8、5、1、5、3、1、9、10]

     

[8、5、5、5、1、1、3、8、9、10]

     

[5、5、5、3、1、1、8、8、9、10]

     

[5、3、5、1、1、5、8、8、9、10]

     

[5、3、1、1、5、5、8、8、9、10]

     

[3,1,1,5,5,5,8,8,9,10]

     

[1、3、5、5、5、5、8、8、9、10]

     

[1、3、5、5、5、5、8、8、9、10]

我不知道如何使第k个最小。我虽然是关于最小堆的,因为最小堆总是索引0,但这是用来制作递减数组吗?

这是我的方法,这是Heapsort。它调用buildHeap,然后进行排序。

//Find kth smallest element-----------------------------------------------------------------------------------------
private int[] findKthSmallestElement(int[] arr, int kthElement) {
    buildheap(arr);
    System.out.println("Max Heap is made: " + Arrays.toString(arr));

    if(kthElement > arr.length){
        System.out.println("Number does not exist.");
        return arr;
    }
    else if(kthElement == arr.length){
        System.out.println(kthElement + " st/nd/th smallest element number" + " is: " + arr[0]);
        return arr;
    }

    heapSize = arr.length - 1;

    for(int i = heapSize; i > 0; i--) {

        swapCurrentNodeWithMaxChild(arr,0, i);

        heapSize--;

        percolateDown(arr, 0,heapSize);

        System.out.println(Arrays.toString(arr));
    }

    return arr;
}

3 个答案:

答案 0 :(得分:0)

如果Invoke(null, null)相对于堆大小k较小,则从 Max 中检索第k个最小的堆是很长的任务-它需要N O((N-k)*logN)~O(N*logN)提取顶部元素的时间。

要解决问题本身-要从未排序的列表中获取最小的k,您不需要完全排序,不需要构建完整堆。

变体1)获取(N-k)的第一个元素,仅为这k个元素构建 max -堆 。遍历所有其他元素。如果当前项目小于堆顶部,请移除顶部并插入当前项目。在最后,堆顶部包含最小的k。复杂度为k

我想如果您现在正在研究堆,则最好使用此变体。

变体2)执行QuickSelect算法(平均复杂度是线性的,但最坏的情况可能会发生)

答案 1 :(得分:0)

  

我试图在最大堆中找到第k个最小的元素。据我了解,我需要对Array进行升序排序,并在得到第k个最小元素时返回。

否,要在最大堆中找到第k个smalles元素,我们只需要从最大堆中提取n-k个元素。无需排序。

  

不会使HeapSort O(N log N),因为它将需要另一个for循环来遍历数组。

我们不需要对数组进行排序,但是请注意,自O(N log N + N) == O(N log N)

以来,遍历数组的一个循环不会改变任何内容。

答案 2 :(得分:0)

您是否需要显式实现算法或可以使用Java API? 如果可以使用API​​,则可以通过Arrays.sort()轻松完成。为了简单起见,我省略了测试k

public void khtElement(k){
    int[] elements = new int[]{10, 9, 8, 5, 1, 8, 3, 5, 5, 1};

    Arrays.sort(elements);
    System.out.println(elements[k-1]);
}