leetcode 373. Find K Pairs with Smallest Sums | 373. 查找和最小的K对数字(小根堆)

这篇博客讨论了如何利用小根堆解决LeetCode上的找K对数之和最小的问题。作者首先介绍了错误的双指针贪心方法,然后揭示了题目实际上需要使用堆来解决。通过创建一个堆,将所有可能的数对插入,然后每次取出堆顶的最小元素,维护堆的结构,从而找到K个最小和的数对。文章提供了详细的代码实现,包括堆的调整和交换操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

https://leetcode.com/problems/find-k-pairs-with-smallest-sums/
在这里插入图片描述

题解

本来以为是个双指针+贪心,但是后来发现如果用双指针的话,指针并不是只能++,还需要往回走,否则会丢失一些组合

看了 Related Topics 之后才发现,这是个考察 Heap 的题。
在这里插入图片描述
相关问题:leetcode 347. Top K Frequent Elements | 347. 前 K 个高频元素(大根堆)

于是复制之前的模板,建了个小根堆,搞定。

class Solution {
    public static class HeapNode {
        int sum;
        int n1;
        int n2;

        public HeapNode(int n1, int n2) {
            this.n1 = n1;
            this.n2 = n2;
            this.sum = n1 + n2;
        }
    }

    public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
        List<List<Integer>> result = new ArrayList<>();
        int heapSize = nums1.length * nums2.length;
        HeapNode[] heap = new HeapNode[heapSize];
        // 建小根堆
        int p = 0;
        for (int n1 : nums1) {
            for (int n2 : nums2) {
                heap[p++] = new HeapNode(n1, n2);
            }
        }
        for (int i = heapSize - 1; i >= 0; i--) // 自下向上建堆 可证复杂度为O(n)
            heapify(heap, i, heapSize);
        // Top k
        for (int i = 0; i < k && i < heap.length; i++) {
            ArrayList<Integer> pair = new ArrayList<>();
            pair.add(heap[0].n1);
            pair.add(heap[0].n2);
            result.add(pair);
            // 堆调整
            swap(heap, 0, --heapSize);
            heapify(heap, 0, heapSize);
        }
        return result;
    }

    public void heapify(HeapNode[] heap, int i, int size) {
        int left = i * 2 + 1;
        while (left < size) {
            int mini = left + 1 < size && heap[left + 1].sum < heap[left].sum ? left + 1 : left; // 左右孩子较小者的下标
            mini = heap[mini].sum < heap[i].sum ? mini : i; // 两个孩子与父节点较小者的下标
            if (mini == i) break; // 不需要交换的情况
            swap(heap, mini, i);
            i = mini; // 更新i使其下沉
            left = 2 * i + 1;
        }
    }

    private void swap(HeapNode[] heap, int i, int j) {
        HeapNode tmp = heap[i];
        heap[i] = heap[j];
        heap[j] = tmp;
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值