You are given two integer arrays nums1 and nums2 sorted in ascending order and an integer k.
Define a pair (u,v) which consists of one element from the first array and one element from the second array.
Find the k pairs (u1,v1),(u2,v2) ...(uk,vk) with the smallest sums.
Example 1:
Given nums1 = [1,7,11], nums2 = [2,4,6], k = 3 Return: [1,2],[1,4],[1,6] The first 3 pairs are returned from the sequence: [1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]
Example 2:
Given nums1 = [1,1,2], nums2 = [1,2,3], k = 2 Return: [1,1],[1,1] The first 2 pairs are returned from the sequence: [1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3]
Example 3:
Given nums1 = [1,2], nums2 = [3], k = 3 Return: [1,3],[2,3] All possible pairs are returned from the sequence: [1,3],[2,3]
优先级队列是不同于先进先出队列的另一种队列,每次从队列中取出的是具有最高优先权的元素。如果不提供Comparator的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头,字符串则按字典序排列。PriorityQueue本质上就是堆排序里面建的最小堆,最小堆满足的一个基本性质是堆顶端的元素是所有元素里最小的那个。堆排序只能保证根是最小(最大),不能保证整体是按照顺序来排序的,只是保证新加入的元素和最近的节点是排序的。
如果想实现按照自己的意愿进行优先级排列的队列的话,需要实现Comparator接口。下面的方法,利用了lambda实现了根据变量sum,来进行优先级队列的建立。
建立类Pair
class Pair {
int[] pair;
int idx2; // current index to nums2
long sum;
Pair(int idx2, int n1, int n2) {
this.idx2 = idx2;
pair = new int[]{n1, n2};
sum = (long) n1 + (long) n2;
}
}
84ms,beats 20%
public List<int[]> kSmallestPairs(int[] nums1, int[] nums2, int k) {
List<int[]> result = new ArrayList<>();
if (nums1 == null || nums2 == null || nums1.length == 0 || nums2.length == 0) return result;
PriorityQueue<Pair> heap = new PriorityQueue<>(k, (a, b) -> (Long.compare(a.sum, b.sum));
for (int i = 0; i < nums1.length && i < k; i++) { // only need first k number in nums1 to start
heap.offer(new Pair(0, nums1[i], nums2[0]));
}
for (int i = 0; i < k && !heap.isEmpty(); i++) { // get the first k sums
Pair p = heap.poll();//get the current smallest pair in heap
result.add(p.pair);
if (p.idx2 < nums2.length - 1) { // get the next value in nums2
int next = p.idx2 + 1;
heap.offer(new Pair(next, p.pair[0], nums2[next]));
}
}
return result;
}
PriorityQueue<Pair> heap = new PriorityQueue<>(k, (a, b) -> (Long.compare(a.sum, b.sum));这里使用的是lambda表达式,性能居然比重新实现 Comparator低。
8ms,beats 92.39%
class CompPair implements Comparator<Pair> {
public int compare(Pair p1, Pair p2) {
return Long.compare(p1.sum, p2.sum);
}
}
public List<int[]> kSmallestPairs(int[] nums1, int[] nums2, int k) {
List<int[]> result = new ArrayList<>();
if (nums1 == null || nums2 == null || nums1.length == 0 || nums2.length == 0) return result;
PriorityQueue<Pair> heap = new PriorityQueue(k, new CompPair());
for (int i = 0; i < nums1.length && i < k; i++) { // only need first k number in nums1 to start
heap.offer(new Pair(0, nums1[i], nums2[0]));
}
for (int i = 0; i < k && !heap.isEmpty(); i++) { // get the first k sums
Pair p = heap.poll();//get the current smallest pair
result.add(p.pair);
if (p.idx2 < nums2.length - 1) { // get the next value in nums2
int next = p.idx2 + 1;
heap.offer(new Pair(next, p.pair[0], nums2[next]));
}
}
return result;
}