使用優先佇列查詢無序陣列中的第 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 次瀏覽

開啟您的 職業生涯

透過完成課程獲得認證

開始學習
廣告