[路飞]_373. 查找和最小的 K 对数字

136 阅读1分钟

「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战

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]
示例 3:
输入: nums1 = [1,2], nums2 = [3], k = 3 
​
输出: [1,3],[2,3]
​
解释: 也可能序列中所有的数对都被返回:[1,3],[2,3]
注意:
  • 1 <= nums1.length, nums2.length <= 105
  • -109 <= nums1[i], nums2[i] <= 109
  • nums1 和 nums2 均为升序排列
  • 1 <= k <= 1000

解题思路

1. 构建一个大顶堆
2. 循环两个数组,分别取出一个值,放入一个数组里面
3. 新数组与堆里面的元素做对比,看是否符合入堆条件,如果符合则进行入堆操作
4. 最后返回堆里的元素即可

代码实现

/**
 * 373. 查找和最小的K对数字
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @param {number} k
 * @return {number[][]}
 */
class BigHeap {
  constructor(k) {
    this.arr = []; // 初始化数组
    this.size = 0; // 初始化长度
    this.max = k; // 初始化最大值
  }
​
  push(val) { // 入堆操作
    this.arr.push(val);
    this.size++;
    if (this.size > 1) {
      let cur = this.size - 1,
        parent = (cur - 1) >> 1;
      while (cur > 0 && compare(this.arr[cur], this.arr[parent])) {
        [this.arr[cur], this.arr[parent]] = [this.arr[parent], this.arr[cur]];
        cur = parent;
        parent = (cur - 1) >> 1;
      }
    }
    if (this.size > this.max) this.pop();
  }
​
  pop() { // 弹出操作
    this.arr[0] = this.arr.pop();
    this.size--;
    let cur = 0,
      childl = 1,
      childr = 2;
    while (
      (childl < this.size && compare(this.arr[childl], this.arr[cur])) ||
      (childr < this.size && compare(this.arr[childr], this.arr[cur]))
    ) {
      if (childr < this.size && compare(this.arr[childr], this.arr[childl])) {
        [this.arr[childr], this.arr[cur]] = [this.arr[cur], this.arr[childr]];
        cur = childr;
      } else {
        [this.arr[childl], this.arr[cur]] = [this.arr[cur], this.arr[childl]];
        cur = childl;
      }
      childl = cur * 2 + 1;
      childr = cur * 2 + 2;
    }
  }
​
  top() { // 获取堆顶元素
    return this.arr[0];
  }
}
function compare(arr1, arr2) { // 比较
  return arr1[0] + arr1[1] > arr2[0] + arr2[1];
}
var kSmallestPairs = function (nums1, nums2, k) {
  const heap = new BigHeap(k);  // 构建堆
​
  for (let i = 0; i < nums1.length; i++) {
    for (let j = 0; j < nums2.length; j++) {
      let temp = [nums1[i], nums2[j]]; // 分别取出来两个数放入数组
      if (heap.size < k || compare(heap.top(), temp)) { // 判断是否符合入堆条件
        heap.push(temp); // 入堆
      } else {
        break;
      }
    }
  }
​
  return heap.arr; // 最后返回结果
};

如果你对这道题目还有疑问的话,可以在评论区进行留言;