查找和最小的 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]
提示:
1 <= nums1.length, nums2.length <= 105
-109 <= nums1[i], nums2[i] <= 109
nums1
和nums2
均为 升序排列1 <= k <= 104
k <= nums1.length * nums2.length
代码结果
运行时间: 95 ms, 内存: 32.1 MB
/*
* 思路:
* 1. 利用 Stream API 的 flatMap 方法将两个数组合并成数对并求和。
* 2. 使用 sorted 方法对数对按和进行排序。
* 3. 使用 limit 方法获取前 k 个数对。
*/
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Solution {
public List<int[]> kSmallestPairs(int[] nums1, int[] nums2, int k) {
return IntStream.range(0, nums1.length)
.boxed()
.flatMap(i -> IntStream.range(0, nums2.length)
.mapToObj(j -> new int[]{nums1[i], nums2[j]}))
.sorted(Comparator.comparingInt(pair -> pair[0] + pair[1]))
.limit(k)
.collect(Collectors.toList());
}
}
解释
方法:
这个题解的思路是使用小根堆来维护当前最小的k个数对。首先将(nums1[0]+nums2[0], 0, 0)放入小根堆中,表示当前最小的数对。然后进行k次循环,每次从堆顶弹出当前最小的数对,并将其加入答案数组。接着,如果该数对的下标j等于0,且i+1
时间复杂度:
O(klogk)
空间复杂度:
O(k)
代码细节讲解
🦆
为什么在初始化小根堆时,只将(nums1[0]+nums2[0], 0, 0)这一对元素加入,而不是从每个数组中各取一个元素加入?
▷🦆
在添加新元素到小根堆时,为什么只在j等于0时检查并添加(nums1[i+1]+nums2[j], i+1, j),这样做有什么特别的原因吗?
▷🦆
在从堆中弹出元素后,为什么要分别检查并添加(nums1[i+1]+nums2[j], i+1, j)和(nums1[i]+nums2[j+1], i, j+1),这两者有什么区别?
▷🦆
在实际操作中,如果k值非常大,超过了所有可能的数对组合的数量,该算法如何处理?
▷相关问题
有序矩阵中第 K 小的元素
给你一个 n x n
矩阵 matrix
,其中每行和每列元素均按升序排序,找到矩阵中第 k
小的元素。
请注意,它是 排序后 的第 k
小元素,而不是第 k
个 不同 的元素。
你必须找到一个内存复杂度优于 O(n2)
的解决方案。
示例 1:
输入:matrix = [[1,5,9],[10,11,13],[12,13,15]], k = 8 输出:13 解释:矩阵中的元素为 [1,5,9,10,11,12,13,13,15],第 8 小元素是 13
示例 2:
输入:matrix = [[-5]], k = 1 输出:-5
提示:
n == matrix.length
n == matrix[i].length
1 <= n <= 300
-109 <= matrix[i][j] <= 109
- 题目数据 保证
matrix
中的所有行和列都按 非递减顺序 排列 1 <= k <= n2
进阶:
- 你能否用一个恒定的内存(即
O(1)
内存复杂度)来解决这个问题? - 你能在
O(n)
的时间复杂度下解决这个问题吗?这个方法对于面试来说可能太超前了,但是你会发现阅读这篇文章( this paper )很有趣。
找出第 K 小的数对距离
数对 (a,b)
由整数 a
和 b
组成,其数对距离定义为 a
和 b
的绝对差值。
给你一个整数数组 nums
和一个整数 k
,数对由 nums[i]
和 nums[j]
组成且满足 0 <= i < j < nums.length
。返回 所有数对距离中 第 k
小的数对距离。
示例 1:
输入:nums = [1,3,1], k = 1 输出:0 解释:数对和对应的距离如下: (1,3) -> 2 (1,1) -> 0 (3,1) -> 2 距离第 1 小的数对是 (1,1) ,距离为 0 。
示例 2:
输入:nums = [1,1,1], k = 2 输出:0
示例 3:
输入:nums = [1,6,1], k = 3 输出:5
提示:
n == nums.length
2 <= n <= 104
0 <= nums[i] <= 106
1 <= k <= n * (n - 1) / 2