使用优先队列查找无序数组中的第 K 小元素


优先队列是一种基于堆的数据结构,它以这样一种方式存储元素,使得最大或最小元素始终位于顶部。给定一个无序数组,我们需要使用优先队列从中找到第 K 小的元素。这里,元素 k 将被给出,并且必须在 1 到给定数组大小的范围内。

示例

让我们借助输入-输出示例来理解这个问题:

输入

int arr[] = {1, 5, 6, 2, 3, 6, 7, 9, 12, 15, 0, 8}
int k = 4

输出

3

解释

在给定的数组中,对数组排序后,我们将得到 3 作为数组的第 4 小元素。

方法 1

在这种方法中,我们将创建一个函数,该函数将给定的数组和数字作为参数,并将第 k 个最小元素作为返回值。

我们将遍历数组,并在 N * log(N) 时间内将数组的所有元素填充到优先队列中。

然后,我们将移除优先队列中的所有元素,直到其大小变为 k,我们将使用 while 循环和优先队列的 pop() 方法来执行此操作。

最后,我们将返回大小为 K 的优先队列的顶部元素,因为它将是所需的数字。

示例

#include <bits/stdc++.h>
using namespace std;

// function to get the kth smallest element 
int findNumber(vector<int>& arr, int k){
   // defining priority queue 
   priority_queue<int>pq;    
   // adding all the elements of the given array to it
   int len = arr.size();
   for(int i=0; i<len; i++){
      pq.push(arr[i]);
   }    
   // now size of the priority queue is N
   // remove all the elements until size is K
   while(pq.size() > k){
      pq.pop();
   }
   // return the final answer 
   return pq.top();
}
int main(){
   vector<int> arr = {1, 5, 6, 2, 3, 6, 7, 9, 12, 15, 0, 8};
   int k = 4; // given k 
   // calling the function 
   cout<< " The kth smallest number in the given array is: " << findNumber(arr,k) << endl;
   return 0;
}

输出

The kth smallest number in the given array is: 3

时间和空间复杂度

以上代码的时间复杂度为 O(N*log(N)),其中 N 是给定数组的大小。

以上代码的空间复杂度为 O(N),因为我们使用了最大大小为 N 的优先队列。

方法 2

这种方法类似于前一种方法,但区别在于它只需要较少的时间复杂度(K 的对数因子),并且优先队列的大小也将是 K,而不是 N。

我们将遍历数组,并将数组的所有元素添加到优先队列中,直到优先队列的大小小于 K。

之后,我们将检查当前数组元素是否大于优先队列的顶部元素,如果是,则可以忽略当前元素,因为队列中已经存在较小的元素。

如果当前元素小于顶部元素,则顶部元素是优先队列中所有 K 个元素中最大的,因此我们将删除顶部元素并将当前元素添加到优先队列中。

最后,我们将返回优先队列的顶部元素,因为它在所有元素中最大。

示例

#include <bits/stdc++.h>
using namespace std;

// function to get the k-th smallest element 
int findNumber(vector<int>& arr, int k){
   // defining priority queue 
   priority_queue<int>pq;
    
   // adding all the elements of the given array to the priority queue 
   int len = arr.size();
   for(int i=0; i<len; i++){
      if(pq.size() < k){
         // if total number of elements in the priority queue is less than k
         // then add this element to the queue
         pq.push(arr[i]);
      } else if(pq.top() < arr[i]){
         // if the top element of the priority queue is smaller than this current element. then just move to the next element
         continue;
      } else {
         // else add this element to the queue 
         pq.pop();
         pq.push(arr[i]);
      }
   }
   return pq.top();
}
int main(){
   // given array
   vector<int> arr = {1, 5, 6, 2, 3, 6, 7, 9, 12, 15, 0, 8};
   int k = 4; // given k 
   // calling the function 
   cout<<"The kth smallest number in the given array is: "<<findNumber(arr,k)<<endl;
   return 0;
}

输出

The kth smallest number in the given array is: 3

时间和空间复杂度

以上代码的时间复杂度为 O(N*log(K)),其中 N 是给定数组的大小,K 是给定的数字,此对数因子是由于优先队列,并且其大小最多可以达到 k。

以上代码的空间复杂度为 O(K),因为我们只在优先队列中存储最大 k 个元素。

结论

在本教程中,我们实现了一个程序,通过使用优先队列从给定数组中找到第 K 小的元素。优先队列是一种基于堆的数据结构,它将最小或最大元素存储在顶部。我们已经实现了两个程序,第一个程序的时间复杂度为 O(N*log(N)),空间复杂度为 O(N),而第二个程序在时间和空间复杂度中都具有 K 的因子。

更新于: 2023年8月24日

339 次浏览

开启您的 职业生涯

通过完成课程获得认证

开始学习
广告