算法通关村第14关【白银】| 堆的经典问题

1.数组中的第k个最大元素

算法通关村第14关【白银】| 堆的经典问题_第1张图片

思路:

  • 最直观的就是选择法,遍历一k次找到第k大的数
  • 之前使用快速排序的思想每次找出一个位置,会超时
  • 这里使用堆(优先队列),找最大用小堆,找最小用大堆。

例如找第k大的数,新建一个空间为k的最小优先队列,只要比当前优先队列最小值大就替换进去,这样全部的数遍历一遍,里面留下的就是前k大的数了,其他的全被替换出去了,并且队头是第k最大的。

class Solution {
    public int findKthLargest(int[] nums, int k) {
        PriorityQueue pq = new PriorityQueue<>(k);
        for(int n : nums){
            if(pq.size()pq.peek()){
                    pq.poll();
                    pq.offer(n);
                }
            }
        }
        return pq.peek();
    }
}

2.堆排序原理

  1. 构建最大堆(Max Heap):首先,将待排序的元素构建成一个最大堆。最大堆是一个满足堆性质的二叉树,即每个节点的值都大于或等于其子节点的值,根节点是堆中的最大元素。

    构建最大堆的过程:从数组中的最后一个非叶子节点开始,逐个向前处理每个节点,将当前节点与其子节点比较并进行交换,直到整个数组构建成一个最大堆。
  2. 排序:一旦构建了最大堆,最大元素就位于堆的根节点(数组的第一个元素)。将根节点(最大元素)与数组中的最后一个元素交换,然后将数组的大小减1,将根节点下沉到适当位置,以保持剩余元素的最大堆性质。重复这个过程,直到整个数组有序。

 堆排序的时间复杂度为O(n * log n),其中n是待排序数组的元素数量。由于堆排序是一种原地排序算法,不需要额外的辅助空间,因此它在空间复杂度上表现较好。堆排序的稳定性取决于在构建最大堆时是否采用稳定的下沉方法,通常情况下是不稳定的排序算法。

3.合并k个升序链表

算法通关村第14关【白银】| 堆的经典问题_第2张图片

思路:题目要求从小到大排序构造一个新的链表,这里要保证每次加入的元素是当前最小的,使用优先队列构造小根堆。将ListNode数组第一个元素加入队列,每次取出队头然后加入取出的元素的下一个。

PriorityQueue详解可以看 PriorityQueue初始化和方法

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length == 0){
            return null;
        }
        ListNode head = new ListNode(-1);
        PriorityQueue q = new PriorityQueue<>(lists.length,(a,b)->a.val-b.val);
        for(int i = 0;i

你可能感兴趣的:(算法,数据结构)