首页 > 其他分享 >【堆】Leetcode 373. 查找和最小的 K 对数字【中等】

【堆】Leetcode 373. 查找和最小的 K 对数字【中等】

时间:2024-06-13 16:02:57浏览次数:28  
标签:int 复杂度 元素 最小 nums1 查找 373 Leetcode nums2

查找和最小的 K 对数字

  • 给定两个以 非递减顺序排列 的整数数组 nums1 和 nums2 , 以及一个整数 k 。

  • 定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2 。

  • 请找到和最小的 k 个数对 (u1,v1), (u2,v2) … (uk,vk) 。

示例 1:

输入: nums1 = [1,7,11], nums2 = [2,4,6], k = 3
输出: [1,2],[1,4],[1,6]
解释: 返回序列中的前 3 对数:
[1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]

解题思路

  • 使用最小堆(优先队列):利用最小堆来存储当前可能的最小数对,并每次从堆中取出最小的数对。
  • 初始化堆:将数组 nums1 中的前 k 个元素与 nums2 的第一个元素配对并加入堆中。由于数组是有序的,nums1[i] + nums2[0] 一定是 nums1[i] 相关的最小和。
  • 扩展堆:每次从堆中取出最小的数对 (u, v),然后将 (u, v_next)(其中 v_next 是 v 在 nums2 中的下一个元素)加入堆中,一定是 nums2[j] 相关的最小和,nums1[i]相关的最小和和nums2[j]相关的最小和都在一个最小堆中,一定能获取到当前的最小和。
  • 停止条件:重复上述过程直到找到 k 个数对。

Java实现

public class KSmallestPairs {
    public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
        List<List<Integer>> result = new ArrayList<>();
        if (nums1.length == 0 || nums2.length == 0 || k == 0) {
            return result;
        }

        // 最小堆,堆元素是三元组 (sum, i, j)
        PriorityQueue<int[]> minHeap = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));

        // 初始化堆,nums1 中的前 k 个元素与 nums2 的第一个元素配对
        for (int i = 0; i < Math.min(nums1.length, k); i++) {
            minHeap.offer(new int[]{nums1[i] + nums2[0], i, 0});
        }

        // 找到 k 个数对
        while (k-- > 0 && !minHeap.isEmpty()) {
            int[] current = minHeap.poll();  // 从堆中取出最小元素
            int i = current[1];  // 获取第一个数组 nums1 的索引
            int j = current[2];  // 获取第二个数组 nums2 的索引
            List<Integer> pair = new ArrayList<>();
            pair.add(nums1[i]);
            pair.add(nums2[j]);
            result.add(pair);  // 将当前数对加入结果列表

            // 如果 nums2 中有下一个元素,则将 (nums1[i], nums2[j+1]) 加入堆
            if (j + 1 < nums2.length) {
                minHeap.offer(new int[]{nums1[i] + nums2[j + 1], i, j + 1});
            }
        }

        return result;
    }

    // 测试用例
    public static void main(String[] args) {
        KSmallestPairs solution = new KSmallestPairs();
        int[] nums1 = {1, 7, 11};
        int[] nums2 = {2, 4, 6};
        int k = 3;

        List<List<Integer>> result = solution.kSmallestPairs(nums1, nums2, k);
        for (List<Integer> pair : result) {
            System.out.println(pair);
        }
        // 期望输出: [1, 2], [1, 4], [1, 6]
    }
}


时间空间复杂度

  • 时间复杂度:初始化堆的时间复杂度是 O(klogk),因为将最多 k 个元素加入堆。
    在最坏情况下,堆中最多包含 k 个元素,每次操作(插入和删除)需要 O(logk) 时间。因此,总体时间复杂度为 O(klogk+klogk)=O(klogk)

  • 空间复杂度:最小堆最多包含 k 个元素,因此空间复杂度是 O(k)。

标签:int,复杂度,元素,最小,nums1,查找,373,Leetcode,nums2
From: https://blog.csdn.net/FLGBgo/article/details/139650485

相关文章

  • 二分查找
    二分查找非递归intbsearchWithoutRecursion(inta[],intkey){intlow=0;inthigh=a.length-1;while(low<=high){intmid=low+(high-low)/2;if(a[mid]>key)high=mid-1;elseif(a[mid]......
  • Q27 LeetCode350 两个数组交集取小
    使用hashmap记录数字个数,如果nums1中重复数字多,遍历2时则不需要取少如果2中重复数字多,则每次取到就-1,直至map内无值  1classSolution{2publicint[]intersect(int[]nums1,int[]nums2){3HashMap<Integer,Integer>map=newHashMap<>();4......
  • (nice!!!)LeetCode 2813. 子序列最大优雅度(反悔贪心)
    2813.子序列最大优雅度思路:1.先对数组items按profit进行降序排序。2.把前k个最大的profit选中3.再遍历剩余的项目,看看能不能增加类别的数量。因为profit是递减的,所以只有类别的数量能增大的情况下,才考虑从选中的k个项目当中删掉重复的类别项目里面的最小profit。细节......
  • LeetCode132双周赛T3,搜索和DP
    求出最长好子序列Idfs(i,j)表示以nums[i]结尾的,至多有j对相邻元素不同的最长序列的长度转移:枚举p<i,如果nums[p]!=nums[i],就从dfs(p,j-1)+1转移过来如果nums[p]==nums[i],就从dfs(p;j)+1转移过来classSolution{public:intmaximumLength(vector<int......
  • 代码随想录 算法训练营d7 哈希表 Leetcode454 四数相加2 Leetcode383 赎金信 Leetcode
    Leetcode454四数相加2 题目链接简单理解四个数组的数构成元组 相加为0思想:参考力扣第一题两数之和 才用哈希表解决问题通过将ab数组之和存储到哈希表中,并记录次数再通过计算-(c+d)去匹配哈希表如果存在那么count+=次数即可classSolution{publicintfour......
  • (nice!!!)LeetCode 2865. 美丽塔 I(数组、单调栈)
    2865.美丽塔I思路:方法一,时间复杂度0(n^2)。枚举每一个点i作为当前山脉数组的最高点。然后我们通过预处理遍历其前面和后面,来更新两个数组f1、f2。数组f1[i]:表示在满足非递减的情况下,区间0~i,以点i的高度heighs[i]为最高点所能形成的最大高度和。数组f2[i]:表示在满足非......
  • LeetCode 300. 最长递增子序列
    更多题解尽在https://sugar.matrixlab.dev/algorithm每日更新。组队打卡,更多解法等你一起来参与哦!LeetCode300.最长递增子序列,难度中等。动态规划解题思路:遍历数组,对于每个nums[i],检查其之前的所有元素nums[j]0......
  • LeetCode刷题之HOT100之单词搜索
    2024/6/12这两天天气只能用闷、潮、热来描述。整个人像被罩在为了饭菜保温的盖子里,喘气困难、粘稠的空气一次又一次打湿我。唯有空调救我,夏天来了。Anyway,昨天只做了一题,今天早点来做一题。1、题目描述2、逻辑分析给定一个二维字符矩阵和一个单词,求单词是否在这个二维......
  • 代码随想录 算法训练营 d6 哈希表 Leetcode242 有效的字母异位词 Leetcode349 两个数
    哈希表很重要哈希表哈希表场景一般哈希表都是用来快速判断一个元素是否出现集合里一般来说数组模拟哈希set 哈希map不同的场景 当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,se......
  • leetcode刷题-归纳总结
    框架思维124.求⼆叉树中最⼤路径和后序遍历最大路径转换为为求单边最大路径105.根据前序和中序遍历构造二叉树前序遍历,找到根节点构建root,得到左右子树区间,左右子树递归构建注意:1.终止条件2.构建unordered_map230.寻找⼆叉搜索树中的第k⼩的元素⼆叉搜索树即左支树所有......