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]Very interesting problem. The approach is actually BFS. Let (x, y) be the last element position (the first position is (0, 0)) added to result, then the next element will either be (x + 1, y) or (x, y + 1). The rest of the part is just normal BFS.
public List<Integer> kSmallestPairs(int[] nums1, int[] nums2, int k) { List<Integer> rst = new ArrayList<>(); int len1 = nums1.length; int len2 = nums2.length; if (len1 == 0 || len2 == 0) { return rst; } PriorityQueue<int[]> queue = new PriorityQueue<>(k, new Comparator<int[]>() { @Override public int compare(int[] first, int[] second) { return nums1[first[0]] + nums2[first[1]] - (nums1[second[0]] + nums2[second[1]]); } }); boolean[][] visited = new boolean[len1][len2]; queue.add(new int[]{0, 0}); visited[0][0] = true; int[][] neighbors = {{0, 1}, {1, 0}}; while (!queue.isEmpty() && rst.size() < k) { int[] currPos = queue.poll(); rst.add(new int[]{nums1[currPos[0]], nums2[currPos[1]]}); for (int[] n : neighbors) { int x = currPos[0] + n[0], y = currPos[1] + n[1]; if (x < len1 && y < len2 && !visited[x][y]) { queue.add(new int[]{x, y}); visited[x][y] = true; } } } return rst; }