给定两个以 升序排列 的整数数组 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]

    1. var kSmallestPairs = function(nums1, nums2, k) {
    2. m = nums1.length
    3. n = nums2.length
    4. /*二分查找第 k 小的数对和的大小*/
    5. let left = nums1[0] + nums2[0];
    6. let right = nums1[m - 1] + nums2[n - 1];
    7. let pairSum = right;
    8. while (left <= right) {
    9. const mid = left + ((right - left) >> 1);
    10. let cnt = 0;
    11. let start = 0;
    12. let end = n - 1;
    13. while (start < m && end >= 0) {
    14. if (nums1[start] + nums2[end] > mid) {
    15. end--;
    16. } else {
    17. cnt += end + 1;
    18. start++;
    19. }
    20. }
    21. if (cnt < k) {
    22. left = mid + 1;
    23. } else {
    24. pairSum = mid;
    25. right = mid - 1;
    26. }
    27. }
    28. const ans = [];
    29. let pos = n - 1;
    30. /*找到小于目标值 pairSum 的数对*/
    31. for (let i = 0; i < m; i++) {
    32. while (pos >= 0 && nums1[i] + nums2[pos] >= pairSum) {
    33. pos--;
    34. }
    35. for (let j = 0; j <= pos && k > 0; j++, k--) {
    36. const list = [];
    37. list.push(nums1[i]);
    38. list.push(nums2[j]);
    39. ans.push(list);
    40. }
    41. }
    42. /*找到等于目标值 pairSum 的数对*/
    43. pos = n - 1;
    44. for (let i = 0; i < m && k > 0; i++) {
    45. let start1 = i;
    46. while (i < m - 1 && nums1[i] == nums1[i + 1]) {
    47. i++;
    48. }
    49. while (pos >= 0 && nums1[i] + nums2[pos] > pairSum) {
    50. pos--;
    51. }
    52. let start2 = pos;
    53. while (pos > 0 && nums2[pos] == nums2[pos - 1]) {
    54. pos--;
    55. }
    56. if (nums1[i] + nums2[pos] != pairSum) {
    57. continue;
    58. }
    59. let count = Math.min(k, (i - start1 + 1) * (start2 - pos + 1));
    60. for (let j = 0; j < count && k > 0; j++, k--) {
    61. const list = [];
    62. list.push(nums1[i]);
    63. list.push(nums2[pos]);
    64. ans.push(list);
    65. }
    66. }
    67. return ans;
    68. }

    image.png