1. 程式人生 > >703. Kth Largest Element in a Stream(python+cpp)

703. Kth Largest Element in a Stream(python+cpp)

題目:

Design a class to find the kth largest element in a stream. Note
that it is the kth largest element in the sorted order, not the kth
distinct element. Your KthLargest class will have a constructor
which accepts an integer k and an integer array nums, which
contains initial elements from the stream. For each call to the method
KthLargest.add, return the element representing the k

th largest
element in the stream.
Example:

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

Note:


You may assume that nums’ length ≥ k-1 and k ≥ 1.

解釋:
設計一個類,返回資料流中的最大的第k個元素。
注意是流中的,不是陣列中的(215. Kth Largest Element in an Array(python+cpp)),如果是陣列中的可以用快速排序中的partition做。
這道題目需要用堆來做
從小到大排序後總右往左數第k大的數字python的heap是小根堆,如果維持一個大小為k的heap的話,那麼最小的數字(第一個數字)就是最終答案,後續輸入的數字只需要和最小的數字nums[0]相比就好,如果當前的堆的大小小於k,則直接將新元素入堆,否則,當前的堆的大小一定是k

(因為初始化的時候如果nums的長度大於k,已經將堆裁剪為大小為k的堆了),此時需要比較當前的valnums[0]的關係,如果小於就不管,如果大於就彈出堆中的最小值,將val入棧,python中可以直接用heapq.heapreplace(data,val),比先heap.pop()heapq.push()的速度要快得多。
需要有一個變數記錄當前堆的大小。
python程式碼:

class KthLargest(object):

    def __init__(self, k, nums):
        """
        :type k: int
        :type nums: List[int]
        """
        self.data=nums
        self.k=k
        self.size=len(nums)
        heapq.heapify(self.data)
        while self.size>k:
            heapq.heappop(self.data)
            self.size-=1

    def add(self, val):
        """
        :type val: int
        :rtype: int
        """
        if self.size<self.k:
            heapq.heappush(self.data,val)
            self.size+=1
        elif val>self.data[0]:
            heapq.heapreplace(self.data,val)
        return self.data[0]
    
# Your KthLargest object will be instantiated and called as such:
# obj = KthLargest(k, nums)
# param_1 = obj.add(val)

c++程式碼:

#include <algorithm> 
using namespace std;
class KthLargest {
public:
    int heap_size=0;
    int global_k=0;
    vector<int>global_nums;
    KthLargest(int k, vector<int> nums) {
        global_k=k;
        global_nums.assign(nums.begin(),nums.end());
        heap_size=nums.size();
        //c++預設是大根堆,這裡需要用小根堆
        make_heap(global_nums.begin(),global_nums.end(),greater<int>());
        while (heap_size>k)
        {
            pop_heap(global_nums.begin(),global_nums.end(),greater<int>());
            global_nums.pop_back();
            heap_size--;
        }
    }
    
    int add(int val) {
        if (heap_size<global_k)
        {
            global_nums.push_back(val);
            push_heap(global_nums.begin(),global_nums.end(),greater<int>());
            heap_size++;
        }
        else if (val>global_nums[0])
        {
            pop_heap(global_nums.begin(),global_nums.end(),greater<int>());
            global_nums[global_k-1]=val;
            push_heap(global_nums.begin(),global_nums.end(),greater<int>());
        }
        return global_nums[0];
    }
};

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

總結:
1.雖然heapq.heapify(nums)以後nums並不是順序的,但是nums[0]總是代表最小的元素(python heapq預設是小根堆,c++的小根堆也是這樣)
但是如果想實現一個大頂堆怎麼辦?
把在資料進堆的時候把所有資料都取相反數,出來的時候再取一下相反數就可以啦。
2. STL 堆操作
標頭檔案是#include <algorithm>
一般用到這四個:make_heap()pop_heap()push_heap()sort_heap();
(1)make_heap()構造堆
void make_heap(first_pointer,end_pointer,compare_function);
預設比較函式是(<),即最大堆。 函式的作用是將[begin,end)內的元素處理成堆的結構,要改成小根堆的時候,第三個引數變成greater<int>()
(2)push_heap()新增元素到堆
void push_heap(first_pointer,end_pointer,compare_function);
新新增一個元素在末尾,然後重新調整堆序。該演算法必須是在一個已經滿足堆序的條件下。 先在vector的末尾新增元素,再呼叫push_heap
(3)pop_heap()從堆中移出元素 ,
void pop_heap(first_pointer,end_pointer,compare_function);
把堆頂元素取出來,放到了陣列或者是vector的末尾。 要取走,則可以使用底部容器(vector)提供的pop_back()函式。 先呼叫pop_heap再從vector中pop_back元素
(4)sort_heap()對整個堆排序 ,排序之後的元素就不再是一個合法的堆了。
注意push_heap()和pop_heap()的時候也要傳入compare_function