算法 数组 -- 求无序整形数组中最小的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();
    }
}

 

posted on 2026-09-25 12:42  新西兰程序员  阅读(1)  评论(0)    收藏  举报