筆試題--TopK問題

筆試題--TopK問題
   CVTE筆試題 題目:本公司現在要給公司員工發波福利,在員工工作時間會提供大量的水果供員工補充營養。由於水果種類比較多,但是卻又不知道哪種水果比較受歡迎,然後公司就讓每個員工報告了自己最愛吃的k種水果,並且告知已經將所有員工喜歡吃的水果存儲於一個數組中。然後讓我們統計出所有水果出現的次數,並且求出大家最喜歡吃的前k種水果。
    這個題目就是典型的TopK問題,在衆多的數據中求前K個數據。
    觀察題目可以發現,這種題目不僅是簡單的排序,在排序前還需要將相同鍵值的數據合併,所以我們首先可以想到,需要先進行統計所有水果的次數,我們可以通過遍歷數組,來統計次數,但是這種方法當數據龐大時,開銷太大,並不適用。
    我們可以很迅速的想到使用STL的容器map來進行快速的統計次數。map的底層是K/V結構的紅黑樹,具有防冗餘的特性(即當前插入元素已存在時,則插入失敗)
    STL中map的insert接口,返回值的一個pair,pair是一個結構體,包含一個迭代器和一個bool類型的值。即表示若插入成功,則返回一個被插入元素的迭代器,並且將第二個參數設置爲true,否則返回容器中已經存在的和當前插入元素相同的元素的迭代器且將第二個參數設置爲false
                                                                   

    所以我們第一個函數先要來實現計數
    
    這個函數的實現較爲簡單,只要理解map的insert函數的具體實現就可以很容易的實現這個函數。所以在這裏就不過多的講這個函數的實現
    接下來就是TopK問題的關鍵部分,排序比較出TopK,當然當數據過多時,排序算法就有些難以實現,但是也勉強可以算是一種方法
    方法一:使用優先級隊列(優先級隊列的方法較爲簡單,熟悉STL裏的優先級隊列,就可以很容易的實現這個代碼)
    
     
    
    程序運行結果
    
   
    方法二:藉助vector來實現,將map中的數據全部存儲到vector中,然後使用排序算法來對vector中的數據進行排序,但是這種方法具有一定的侷限性,當數據過多時,vector的存儲空間會特別大,排序算法的效率也會比較低
    
     
    
    運行結果:
    
    
    方法三:藉助vector,使用堆排序來實現,求TopK問題,可以建一個K大小的小堆,當數據很多時,也比較方便使用,小堆的堆頂數據是當前K各數中的最小值,當數據和堆頂數據比較時,比堆頂數據大就將原本的堆頂數據pop,將當前數據push。
    
    
    
    
 
    方法四:可以使用set來解決這個問題,但是set容器具有防冗餘的特性,所以當map中的數據的second相等時,set就會出錯,並不會將相等數據插入。但是這種方法也算一種思路,set本身就是排序的,所以使用set方法時,可以免去排序的步驟
    
     
    
    
   
    想要迅速高效的解決此類問題,就必須熟練的掌握使用STL中的容器和算法。