373. Find K Pairs with Smallest Sums

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]
含义:给定两个升序的数组,各抽取一个求和,给出和最小的k对组合

方法一:
 1     public List<int[]> kSmallestPairs(int[] nums1, int[] nums2, int k) {
 2         int len1=nums1.length;
 3         int len2=nums2.length;
 4         List<int[]> res=new ArrayList<int[]>();
 5         if (len1 == 0 || len2 == 0 || k == 0) {
 6             return res;
 7         }
 8         Queue<int[]> queue = new PriorityQueue<int[]>(len1*len2,
 9                 new Comparator<int[]>() {
10                     @Override
11                     public int compare(int[] a, int[] b) {
12                         return a[0]+a[1] - b[0]-b[1];
13                     }
14                 });//由头到尾,节点值升序排列
15         for(int i=0;i<nums1.length;i++){
16             for(int j=0;j<nums2.length;j++){
17                 int[] s=new int[]{nums1[i],nums2[j]};
18                 queue.add(s);
19             }
20         }
21         k = Math.min(k,queue.size());
22         while(k>0){
23             res.add(queue.poll());
24             k--;
25         }
26         return res;        
27     }

方法二:

 1     public List<int[]> kSmallestPairs(int[] nums1, int[] nums2, int k) {
 2         PriorityQueue<int[]> que = new PriorityQueue<>((a, b) -> a[0] + a[1] - b[0] - b[1]);  //由头到尾,节点值升序排列
 3         List<int[]> res = new ArrayList<>();
 4         if (nums1.length == 0 || nums2.length == 0 || k == 0) return res;
 5         for (int i = 0; i < nums1.length && i < k; i++) que.offer(new int[]{nums1[i], nums2[0], 0});  //最后一个0表示选取了nums2中位置0的数
 6         while (k-- > 0 && !que.isEmpty()) {
 7             int[] cur = que.poll();
 8             res.add(new int[]{cur[0], cur[1]});
 9             if (cur[2] == nums2.length - 1) continue;//cur[2] 表示选取了nums2中位置cur[2]的数,达到数组右边界了,所以continue
10             que.offer(new int[]{cur[0], nums2[cur[2] + 1], cur[2] + 1});//nums1中的当前值和nums2中位置cur[2]+1的数构成新的组合加入优先队列中
11         }
12         return res;
13     }
原文地址:https://www.cnblogs.com/wzj4858/p/7729923.html