Leetcode 703. 數據流中的第K大元素


1.題目要求

設計一個找到數據流中第K大元素的類(class)。注意是排序后的第K大元素,不是第K個不同的元素。

你的 KthLargest 類需要一個同時接收整數 k 整數數組nums 的構造器,它包含數據流中的初始元素。每次調用 KthLargest.add,返回當前數據流中第K大的元素。

示例:

  int k = 3;
  int[] arr = [4,5,8,2];
  KthLargest kthLargest = new KthLargest(3, arr);
  kthLargest.add(3);   // returns 4
  kthLargest.add(5);   // returns 5
  kthLargest.add(10);  // returns 5
  kthLargest.add(9);   // returns 8
  kthLargest.add(4);   // returns 8

說明:
你可以假設 nums 的長度≥ k-1 且k ≥ 1。

 

2.解題思路

一般地,堆和堆排序——解決 "貪心算法及其類似問題" 的利器。

# 思路:我們可以用一個小根堆來做,並且限制堆的大小為k,初始化時把nums的每個數都push到堆中,如果堆的大小大於k,就pop一個元素。對於add方法也是同理。

# 這里使用的數據結構是C++中的“優先隊列(priority_queue)",包含在頭文件<queue>中。優先隊列具有隊列的所有特性,包括基本操作,只是在這基礎上添加了內部的一個排序,它本質是一個堆實現的。

定義:priority_queue<Type, Container, Functional>

       Type 就是數據類型
       Container 就是容器類型(Container必須是用數組實現的容器,比如vector,deque等等,但不能用 list。STL里面默認用的是vector),
       Functional 就是比較的方式,當需要用自定義的數據類型時才需要傳入這三個參數,使用基本數據類型時,只需要傳入數據類型,默認是大根堆
 
//降序隊列(大根堆)
priority_queue <int,vector<int>,less<int> >q;
 
//升序隊列(小根堆)
priority_queue <int,vector<int>,greater<int> > q;
 
另外,greater和less是std實現的兩個仿函數(就是使一個類的使用看上去像一個函數。其實現就是類中實現一個operator(),這個類就有了類似函數的行為,就是一個仿函數類了)
 
//示例
#include<iostream> #include <queue> using namespace std; int main() { //對於基礎類型 默認是大頂堆 priority_queue<int> a; //等同於 priority_queue<int, vector<int>, less<int> > a; // 這里一定要有空格,不然成了右移運算符↓ priority_queue<int, vector<int>, greater<int> > c; //這樣就是小頂堆 priority_queue<string> b; for (int i = 0; i < 5; i++) { a.push(i); c.push(i); } while (!a.empty()) { cout << a.top() << ' '; a.pop(); } cout << endl; while (!c.empty()) { cout << c.top() << ' '; c.pop(); } cout << endl; b.push("abc"); b.push("abcd"); b.push("cbd"); while (!b.empty()) { cout << b.top() << ' '; b.pop(); } cout << endl; return 0; }

 

//輸出

4 3 2 1 0
0 1 2 3 4
cbd abcd abc

 

3.我的代碼

Leetcode上提交的執行時間為36ms.

/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest obj = new KthLargest(k, nums);
* int param_1 = obj.add(val);
*/

class KthLargest {
public:
    KthLargest(int k, vector<int> nums) {
        //限制堆的大小為k
        size = k;
        
        for (int i = 0; i < nums.size(); i++){            
            heap.push(nums[i]);

            //堆大小超過k,pop出一個元素            
            if (heap.size() > k) heap.pop();        
        }    
    }    
        //操作原理同上
        int add(int val) {        
            heap.push(val);        
            if (heap.size() > size) heap.pop();        
            return heap.top();    }

private:
    //升序隊列(小根堆),STL中存在的一種優先隊列,本質用堆實現的
    priority_queue<int, vector<int>, greater<int>> heap;    
    int size;
};
 

 

 

 

4.用時更少的范例

這是leetcode上執行時間最短的提交代碼,執行時間為28ms。思路同上,代碼幾乎相同。雖然運行快了一些,但是個人認為上面解法中的代碼寫法更加安全規范

因為,一般“數據元素”都是定為private的,這樣程序安全性更高。

 

class KthLargest {
public:

    //定義放在前面了
    priority_queue<int, vector<int>, greater<int>> pq;
    int size;

    KthLargest(int k, vector<int> nums) {
        size=k;
        for(int i=0;i<nums.size();i++) {
            pq.push(nums[i]);
            if(pq.size()>k) pq.pop();
        }
    }
    
    int add(int val) {
        pq.push(val);
        if(pq.size()>size) pq.pop();
        return pq.top();
    }
};
 

 

參考博客:

1:https://blog.csdn.net/qq_26410101/article/details/81977685     Kth Largest Element in a Stream 數據流中的第K大元素

2:https://blog.csdn.net/weixin_36888577/article/details/79937886    c++優先隊列(priority_queue)用法詳解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM