Skip to content
On this page

373. 查找和最小的K对数字

原题链接:LeetCode 373. 查找和最小的K对数字

题目描述

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

提示:

1 <= nums1.length, nums2.length <= 105
-109 <= nums1[i], nums2[i] <= 109
- `nums1` 和 `nums2` 均为 **升序排列**

1 <= k <= 104
- `k <= nums1.length * nums2.length`

难度: Medium


题解代码

javascript
/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @param {number} k
 * @return {number[][]}
 */

// 暴力堆--超时
var kSmallestPairs = function(nums1, nums2, k) {
  const heap = []
  let count = 0
  for (let i = 0; i < nums1.length; i++) {
    for (let j = 0; j < nums2.length; j++) {
      if (count < k) {
        heap.push([nums1[i], nums2[j]])
        if (count === k - 1) genHeap(heap, k, 0)
      } else {
        if ((heap[0][0] + heap[0][1]) > (nums1[i] + nums2[j])) {
          heap[0] = [nums1[i], nums2[j]]
          maxHeapify(heap, k, 0)
        }
      }
      count++
    }
  }
  return heap

  function genHeap(arr, size) {
    for (let i = Math.floor(arr.length / 2); i >= 0; i--) {
      maxHeapify(arr, size, i)
    }
  }
  
  function maxHeapify(arr, size, i) {
    const l = i * 2 + 1
    const r = i * 2 + 2
    let max = i
    const val = idx => arr[idx][0] + arr[idx][1]
    if (l < size && val(l) > val(max)) {
      max = l
    }
    if (r < size && val(r) > val(max)) {
      max = r
    }
    if (max !== i) {
      [arr[max], arr[i]] = [arr[i], arr[max]]
      maxHeapify(arr, size, max)
    }
  }
};

// 手写堆
var kSmallestPairs = function(nums1, nums2, k) {
  const heap = []
  const res = []
  const len = Math.min(nums1.length, k)
  for (let i = 0; i < len; i++) {
    heap.push([i, 0])
  }
  genHeap(heap)
  while ( res.length < k && heap.length) {
    const [i, j] = heap.shift()
    res.push([nums1[i], nums2[j]])
    if (j + 1 < nums2.length) heap.unshift([i, j + 1])
    minHeapify(heap, 0)
  }
  return res

  function genHeap (heap) {
    for (let i = Math.floor(heap.length / 2); i >= 0; i--) {
      minHeapify(heap, i)
    }
  }

  function minHeapify (heap, i) {
    const l = i * 2 + 1
    const r = i * 2 + 2
    let min = i
    const size = heap.length
    const val = idx => nums1[heap[idx][0]] + nums2[heap[idx][1]]
    if (l < size && val(l) < val(min)) {
      min = l
    }
    if (r < size && val(r) < val(min)) {
      min = r
    }
    if (min !== i) {
      [heap[i], heap[min]] = [heap[min], heap[i]]
      minHeapify(heap, min)
    }
  }
};


// 内置堆
var kSmallestPairs = function (nums1, nums2, k) {
  const res = [];
  // leetcode 内置API
  const pq = new MinPriorityQueue({ 
    compare: (a, b) => nums1[a[0]] + nums2[a[1]] - (nums1[b[0]] + nums2[b[1]]) 
  });

  for (let i = 0; i < Math.min(k, nums1.length); i++) pq.enqueue([i, 0]);

  while (res.length < k && pq.size()) {
      const [i, j] = pq.dequeue();
      if (j + 1 < nums2.length) pq.enqueue([i, j + 1]);
      res.push([nums1[i], nums2[j]]);
  }

  return res;
};

技术文档集合