js(64)~373. 查找和最小的 K 对数字

91 阅读1分钟

力扣本题传送门

这个大顶堆,这两天都在看这个大顶堆,小顶堆,我看题解有几个大顶堆能看懂,但是他们的代码都提交超时,找了一个不超时的,比这写了一遍,中间用了 位运算符,然后我看不懂了.. 代码如下

/*
 * @lc app=leetcode.cn id=373 lang=javascript
 *
 * [373] 查找和最小的 K 对数字
 */

// @lc code=start
/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @param {number} k
 * @return {number[][]}
 */
var kSmallestPairs = function (nums1, nums2, k) {
	const pq = new Heap([], (a, b) => a[0] + a[1] < b[0] + b[1]);
	for (const num1 of nums1) {
		for (const num2 of nums2) {
			const item = [num1, num2];
			pq.push(item);
			if (pq.size > k) {
				// 引用相同 说明后面的数字都会出队 所以可以提前推出
				if (pq.pop() === item) {
					break;
				}
			}
		}
	}

	return pq.getData()
};
// 最大堆
class Heap {
	constructor(data, cmp) {
		this.data = [null].concat(data);
		this.cmp = cmp;
		// 这个>> 目前还是理解不了啊
		for (let i = data.length >> 1; i > 0; i--) { this.down(i) }
	}
	get size() {
		return this.data.length - 1;
	}
	get top() {
		return this.data[1];
	}
	// 返回1以后的
	getData() {
		return this.data.slice(1)
	}
	swap(i, j) {
		[this.data[i], this.data[j]] = [this.data[j], this.data[i]];
	}
	up(i) {
		if (i <= 1) {
			return;
		}
		const p = i >> 1;
		if (this.cmp(this.data[p], this.data[i])) {
			this.swap(i, p);
			this.up(p);
		}
	}
	down(i) {
		let j = i;
		const n = this.data.length;
		if (i > n - 1) {
			return;
		}
		const l = i << 1, r = l + 1;
		if (l < n && this.cmp(this.data[i], this.data[l])) {
			i = l;
		}
		if (r < n && this.cmp(this.data[i], this.data[r])) {
			i = r;
		}
		if (j !== i) {
			this.swap(i, j);
			this.down(i);
		}
	}
	push(item) {
		this.up(this.data.push(item) - 1)
	}
	pop() {
		this.swap(1, this.data.length - 1);
		const res = this.data.pop();
		this.down(1);
		return res;
	}
}
// @lc code=end