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>
priority_queue <int,vector<int>,less<int> >q;
priority_queue <int,vector<int>,greater<int> > q;
//示例
#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)用法詳解