当前位置: 首页 > article >正文

51-TOP-K问题练习-LeetCode373查找和最小的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]

示例 2:

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

示例 3:

输入: nums1 = [1,2], nums2 = [3], k = 3
输出: [1,3],[2,3]
解释: 也可能序列中所有的数对都被返回:[1,3],[2,3]

提示:

    1 <= nums1.length, nums2.length <= 10^5
    -10^9 <= nums1[i], nums2[i] <= 10^9
    nums1 和 nums2 均为升序排列
    1 <= k <= 1000


思路

先将所有可能的组合对(u,v)筛选出来。外层循环取u——第一个元素;内层循环取v——第二个元素。

用一个大小为k的最大堆存储组合对,即优先级队列中存储类的对象(比存数组好用)。

k的大小和数组长度没有直接关系,需要判断边界。

示例 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]

此时k == nums1.length || nums2.length,当然要把整个数组遍历完。在n个升序元素中,取前n个元素,当然要整个遍历。

示例 2:

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

此时k < nums1.length || nums2.length,遍历数组只需走k步即可。要从n个升序数组中,取前k个最小值,只需要从第一个元素开始走k步即可。

此处的数组遍历是双重循环,u-来自于nums1,v-来自于nums2。要把nums1和nums2都走一遍。

nums1 = [1,1,2]:u,k < nums1.length,因此2这个值肯定用不到,最多走到第2个1就结束。

nums2 = [1,2,3]:v,k < nums2.length,因此3这个值肯定用不到,最多走到第2个2就结束。

拿着nums1数组中的第一个1去遍历nums2数组中的[1,2],得到[1,1],[1,2]。

拿着nums1数组中的第二个1去遍历nums2数组中的[1,2],得到[1,1],[1,2]。

在最终得到的[1,1],[1,2],[1,1],[1,2]四个集合中选出前2个和最小的组合,得到[1,1],[1,1]。

示例 3:

输入: nums1 = [1,2], nums2 = [3], k = 3
输出: [1,3],[2,3]
解释: 也可能序列中所有的数对都被返回:[1,3],[2,3]

此时k > nums1.length || nums2.length,排列组合的个数<k,遍历整个数组。

总结:

以上三种情况,我们在遍历数组时不是直接遍历结束,而是走Math.min(k, nums.length)。


代码

class Solution {
    //此时Pair类就具备可比较能力
    private class Pair implements Comparable<Pair> {
        //第一个数组元素
        int u;
        //第二个数组元素
        int v;

        //构造方法
        public Pair(int u, int v) {
            this.u = u;
            this.v = v;
        }

        @Override
        public int compareTo(Pair o) {
            //取小用大,将JDK内置的最小堆转化为最大堆
            return (o.u + o.v) - (this.u + this.v);
        }
    }

    public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
        Queue<Pair> queue = new PriorityQueue<>();

        //最外层取u值
        for (int i = 0; i < Math.min(nums1.length, k); i++) {
            //最内层取v值
            for (int j = 0; j < Math.min(nums2.length, k); j++) {
                if(queue.size() < k) {
                    queue.offer(new Pair(nums1[i], nums2[j]));
                } else {
                    Pair pair = queue.peek();
                    if (nums1[i] + nums2[j] < (pair.u + pair.v)) {
                        queue.poll();
                        queue.offer(new Pair(nums1[i], nums2[j]));
                    }
                }
            }
        }

        //队列中就存储了前k个最小的pair对象
        //List套List,二维数组
        List<List<Integer>> ret = new ArrayList<>();
        //边界条件 k > queue.size();
        for (int i = 0; i < k && !(queue.isEmpty()); i++) {
            List<Integer> temp = new ArrayList<>();
            Pair pair = queue.poll();
            temp.add(pair.u);
            temp.add(pair.v);
            ret.add(temp);
        }
        return ret;
    }
}

承上启下:

  • 二叉树:理论基础,无实际用处,做个题。
  • 二分搜索树:TreeSet、TreeMap、红黑树、二分平衡搜索树。(在Java标准库中)
  • 哈希表:HashSet、HashMap。(在Java标准库中)
  1. Set:存储不重复元素的线性表。若只是判定元素是否存在,或者过滤重复元素,使用Set集合。
  2. Map:存储key-value键值对。存储的数据是一种映射关系,需要根据不重复的key对应value,则需要使用Map集合。(例:身份证号=姓名)
  • Set和Map是一种专门用来进行搜索的容器/数据结构,其搜素的效率与其具体的实例化子类有关。
  • 尽量不要用Map和Set集合进行遍历,对于这俩集合的遍历操作,是效率比较低的操作。使用Set和Map集合最核心的操作是搜索。


http://www.kler.cn/a/5179.html

相关文章:

  • 网络数据被网卡接收后在电脑内部的流转过程
  • 龙蜥开发者说:给芯片以系统、给系统以社区 | 第 17 期
  • Kotlin 是后端开发的未来
  • Spring Cloud实现微服务- 熔断机制
  • 2023年四月份图形化三级打卡试题
  • Jenkins自动化部署实例讲解
  • 【WEB前端进阶之路】 HTML 全路线学习知识点梳理(中)
  • 倒计时时钟
  • UNIX环境高级编程——UNIX基础知识
  • 实战:向人工智能看齐用Docker部署一个ChatGPT
  • 科大奥瑞物理实验——半导体封装实验
  • python -m pip install --upgrade pip 升级失败
  • 2023-04-01 解决使用sort()方法对数字数组排序失效的问题,sort()方法的参数:比较函数,如何根据对象属性,将对象构成的数组进行排序?
  • linux基础之计算机基础
  • ChatGPT 出现严重技术漏洞,“当红炸子鸡”翻车了?
  • Unity创建自定义脚本模板
  • 文件操作—IO
  • 力扣刷题笔记21——两个链表的第一个公共节点/栈方法和双指针法
  • Typescript快速入门
  • TCP连接的三次握手和连接释放的四次挥手图文详解