算法 数组 -- 求无序整形数组中最小的K个数
这个算法题是求一个无序的整形数组中,最小的K个数
比如 整形数组 [6,3,8,2,1] => 比如,求这个整形数组里面最小的4个数据,那应该是 [6,3,2,1]
这个题目我们用.NET6+ 中的 PriorityQueue(优先级队列) 来实现. PriorityQueue默认是小根堆
堆Heap是一种线性排序的完全二叉树数据结构, 每个节点的值都大于或小于它的左右孩子
大根堆 -- 每个节点的值都大于它的左右孩子,所以根节点是最大的
小根堆 -- 每个节点的值都小于它的左右孩子,所以根节点是最小的
所以这道题我们的解法就差不多出来了, 因为最终是从数组中获取K个数,所以我们先从原数组中取位置从0到 (K-1)的这K个数,放入PriorityQueue中
然后在循环数组中从位置K到数组尾部的其他元素,只要是小于 < PriorityQueue中最大数 的元素,就放入PriorityQueue, 替换掉PriorityQueue中的这个最大数
=》 所以,这里关键点就成了,需要很快知道PriorityQueue中的最大数 => 如果它是大根堆,那就好办了,根节点就是,peek方法取出来的就是优先级最高的根节点
但现在PriorityQueue默认是小根堆,优先级最高的是值最小的,比如 上面的数组 [6,3,8,2,1], 如果我们把优先级值也设置成元素值,如下
| PriorityQueue | |
| 元素 | 优先级 |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 6 | 6 |
| 8 | 8 |
我们根据上面的描述,我们要取出PriorityQueue的最大数8. 但现在PriorityQueue是小根堆,Peek()方法取出的是优先级数字最小的,也就是1,而不是8 => 那怎么办?
=》 显然,我们需要Peek()方法取出的是8, 那就要让它对应的优先级数字最小 =》 取负数 -8是这里吗最小的,这样它的优先级就变成最高了,Peek()方法取出的就是8,而不是1了
代码如下
public class Solution { public int[] GetLowestKInArray(int[] arr, int k) { var kQueue = new PriorityQueue<int,int>(); foreach(var item in arr) { if(kQueue.Count < k) { kQueue.Enqueue(item,-item); } else { var topPriority = kQueue.Peek(); if(item < topPriority) { kQueue.Dequeue(); kQueue.Enqueue(item,-item); } } } var result = new List<int>(); while(kQueue.Count > 0) { result.Add(kQueue.Dequeue()); } return result.ToArray(); } }
浙公网安备 33010602011771号