这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战
大家好今天给大家分享下一道 LeetCode 简单难度 的题目[剑指 Offer 40. 最小的k个数](leetcode-cn.com/problems/gr…)
题目
输入整数数组
arr,找出其中最小的k个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例 1: 输入:arr = [3,2,1], k = 2 输出:[1,2] 或者 [2,1] 示例 2: 输入:arr = [0,1,2,1], k = 1 输出:[0]
分析
1.整数数组
2.有重复值
3.有负数
4.输出最小的k个数的数组
解法
1.sort
2.maxHeap
解法一:sort
思路
1.排序后单向递增
2.取最小的前k个数
*/
var getLeastNumbers = function (arr, k) {
return arr.sort((a, b) => a - b).slice(0, k);
};
/* 复杂度
时间 O(logn)
空间 O(logn)
*/
解法二:maxHeap
思路
1.书写最大堆栈的类
2.利用最大堆栈存入所有的元素
3.取出arr.len-k个元素
4.返回 剩下的元素就是最小的元素
*/
// maxHeap的写法借鉴 https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/solution/chao-quan-3chong-jie-fa-zhi-jie-pai-xu-zui-da-dui-/
// 交换元素
function swap(arr, i, j) {
const temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
class MaxHeap {
constructor(arr) {
this.array = [];
if (Array.isArray(arr)) {
// 把输入的arr 变成最大堆的方式
for (const item of arr) {
this.insert(item);
}
}
}
// 插入
insert(item) {
// 先把元素放入最后面
this.array.push(item);
let index = this.array.length - 1;
// 维护maxHeap的结构,向上比较 最终保证,父级一定大于子级
this.heapifyUp(index);
}
heapifyUp(index) {
// 不断的比较父类,最终形成一个最大堆的树形结构
while (index) {
// 求出父类的索引 Math.floor((index-1)/2)
let parentIndex = Math.floor((index - 1) / 2);
const child = this.array[index];
const parent = this.array[parentIndex];
// 比较父类的元素,如果比父类大则和父类交换位置
if (child > parent) {
swap(this.array, index, parentIndex);
index = parentIndex;
} else {
break;
}
}
}
// 删除的方法
extract() {
if (!this.array.length) return null;
// 把maxHeap的根部元素和后面的元素想替换
swap(this.array, 0, this.array.length - 1);
const res = this.array.pop();
const index = 0;
// 维护maxHeap的结构,向下比较 最终保证,父级一定大于子级
this.heapifyDown(index);
return res;
}
heapifyDown(index) {
const length = this.array.length;
//求出根部的左子元素
let exchange = 2 * index + 1; // 左边
//不断和子元素比较,最终达到 根部元素最大
while (exchange < length) {
const right = 2 * index + 2;
// 如果右边的元素比较大,则把元素替换成右边的元素 然后比较,反正保持替换后父级一定大于子级的元素
if (right < length && this.array[exchange] < this.array[right]) {
exchange = right;
}
if (this.array[exchange] <= this.array[index]) {
break;
}
swap(this.array, exchange, index);
index = exchange;
exchange = index * 2 + 1;
}
}
top() {
if (this.array.length) return this.array[0];
return null;
}
}
var getLeastNumbers = function (arr, k) {
// 把所有元素都入heap
const maxHeap = new MaxHeap(arr);
//取出arr.length-k
for (let i = 0; i < arr.length - k; i++) {
maxHeap.extract();
}
// 剩下的就是最小的k个数
return maxHeap.array;
};
/* 复杂度
时间 O(nLogn)
空间 O(n)
*/
总结
这道题考察的对maxHeap的应用,利用maxHeap中根为最大值的特性来求解,另外使用sort也是很常见的一种取最小值区间的一个方法
大家可以看看我分享的一个专栏(前端搞算法)里面有更多关于算法的题目的分享,希望能够帮到大家,我会尽量保持每天晚上更新,如果喜欢的麻烦帮我点个赞,十分感谢
大家如果对“TS”感兴趣的可以看看我的专栏 (TypeScript常用知识),感谢大家的支持
文章内容目的在于学习讨论与分享学习算法过程中的心得体会,文中部分素材来源网络,如有侵权,请联系删除,邮箱 182450609@qq.com