算法通关村-----堆在查找和排序中的应用

数组中的第K个最大元素

问题描述

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。详见leetcode215

问题分析

可以创建一个包含k个元素的最小堆,初始时,将数组元素中的前K个放入堆中,之后,遍历数组中的其他元素,与堆顶元素比较,只有大于堆顶元素,才将该元素与堆顶元素替换(即先执行删除,在执行插入),遍历结束后,堆顶元素即是数组中第K大的元素。

代码实现

public int findKthLargest(int[] nums, int k) {
	if(k>nums.length){
	    return -1;
	}
	PriorityQueue<Integer> minHeap = new PriorityQueue<>(4, (a, b) -> a - b);
	for(int i=0;i<k;i++){
	    minHeap.offer(nums[i]);
	}
	for(int i=k;i<nums.length;i++){
	    if(nums[i]>minHeap.peek()){
	        minHeap.poll();
	        minHeap.offer(nums[i]);
	    }
	}
	return minHeap.poll();
}

堆排序

问题描述

给定整数数组nums,使用堆排序对数组中的元素进行排序。

问题分析

使用堆排序对数组元素进行排序

代码实现

public static void heapSort(int[] nums){
	PriorityQueue<Integer> minHeap = new PriorityQueue<>(nums.length,(a,b) -> a-b);
	for (int i = 0; i < nums.length; i++) {
	    minHeap.offer(nums[i]);
	}
	for (int i = 0; i < nums.length; i++) {
	    nums[i] = minHeap.poll();
	}
}

合并K个有序链表

问题描述

给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。详见leetcode23

问题分析

链表数组中存放的其实是每个链表的头节点,可以根据链表的长度创建相同大小的最小堆,将链表中的节点放入堆中,之后,取堆顶元素,即为最小元素,并取出元素的下一个元素放入堆中。

代码实现

public ListNode mergeKLists(ListNode[] lists) {
    PriorityQueue<ListNode> minHeap = new PriorityQueue<ListNode>((a,b) -> a.val-b.val);
    for(int i=0;i<lists.length;i++){
        if(lists[i]!=null){
            minHeap.offer(lists[i]);
        }
    }
    ListNode vhead = new ListNode(-1);
    ListNode iter = vhead;
    while(!minHeap.isEmpty()){
        ListNode node = minHeap.poll();
        iter.next = node;
        iter = node;
        if(iter.next!=null){
            minHeap.offer(iter.next);
        }
    }
    return vhead.next;
}

总结

堆查找和排序的应用主要是指堆排序和查找最大最小元素,或者第几大,第几小元素的问题上。这里我们遵循的原则是:

查找:查大用小堆,查小用大堆

排序: 升序用小堆,降序用大堆

堆的操作过程比较复杂,在java中,可以使用优先队列实现堆的操作,因为java中的优先队列是基于堆实现的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天不coding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值