题目:
给定两个以升序排列的整形数组 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]
思路:
考虑题目的特殊性,两个数组都是升序,利用小根堆,维护一个容量为k的小根堆,堆内的每个元素是arr[],其内都有两个数。
Java
package leetcodeTest;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.PriorityQueue;
public class S373_kSmallestPairs_new {
public ArrayList<ArrayList<Integer>> kSmallestPairs(int[] num1, int[] num2, int k){
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
//创建一个小根堆
PriorityQueue<int[]> pQ = new PriorityQueue<int[]>(k, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return twoSum(o2)- twoSum(o1);
}
});
int pre_n1 = 0x7fffffff;
int pre_n2 = 0x7fffffff;
for (int n1: num1)
for (int n2: num2){
if (n1 > pre_n1 && n2 > pre_n2)
break;
int[] arr = new int[]{n1, n2};
if (pQ.size() < k)
pQ.add(arr);
else if (pQ.size() >=k && twoSum(arr)< twoSum(pQ.peek())){
pQ.poll();
pQ.add(arr);
pre_n1 = n1;
pre_n2 = n2;
}
}
while (!pQ.isEmpty()){
ArrayList<Integer> list = new ArrayList<Integer>();
int[] arr = pQ.poll();
list.add(arr[0]);
list.add(arr[1]);
res.add(list);
}
return res;
}
public int twoSum(int[] arr){
return arr[0]+arr[1];
}
public static void main(String[] args){
S373_kSmallestPairs_new s373 = new S373_kSmallestPairs_new();
int[] num1 = {1,7,11};
int[] num2 = {2,4,6};
System.out.println(s373.kSmallestPairs(num1, num2, 3));
}
}