1. 程式人生 > >LeetCode347. 前K個高頻元素

LeetCode347. 前K個高頻元素

今天繼續哈,寫的還是比較簡單的一個題,雜湊表和堆排序,要多多熟悉java的資料結構。

題目

給定一個非空的整數陣列,返回其中出現頻率前 高的元素。

例如,

給定陣列 [1,1,1,2,2,3] , 和 k = 2,返回 [1,2]

注意:

  • 你可以假設給定的 總是合理的,1 ≤ k ≤ 陣列中不相同的元素的個數。
  • 你的演算法的時間複雜度必須優於 O(n log n) , 是陣列的大小。

分析

看到給出一個數組,輸出頻率最高的第一反應就是雜湊表嘛, 因為輸出頻率前k高的元素,所以要進行一次排序,注意裡要求,時間複雜度必須優於O(n log n),堆排序是時間複雜度為O(n log n),這樣就用了優先佇列PriorityQueue。

首先遍歷陣列,將陣列中的數字和出現的對應頻率存入map中,這裡可以把map中的鍵值對分散為一個一個的Map.Entry<K,V>,對value排序存放入堆中,最後將前k大的出隊。

java的優先佇列預設為小頂堆,在建立堆的時候要寫一下比較器,通過entry的value值進行降序排序。

程式碼

class Solution {
    public List<Integer> topKFrequent(int[] nums, int k) {
        List<Integer> list = new ArrayList<>();
        
        PriorityQueue<Map.Entry<Integer,Integer>> pq = new PriorityQueue<>(new Comparator<Map.Entry<Integer, Integer>>() {
            @Override
            public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
                return o2.getValue()-o1.getValue();
            }
        });

        Map<Integer,Integer> map = new HashMap<>();
        
        for (int i = 0; i < nums.length; i++) 
            if (map.containsKey(nums[i]))
                map.put(nums[i],map.get(nums[i])+1);
            else
                map.put(nums[i],1);

        Set<Map.Entry<Integer,Integer>> set = map.entrySet();
        
        for (Map.Entry<Integer,Integer> entry : set)
            pq.add(entry);
        

        for (int i = 0; i < k; i++) 
            list.add(pq.poll().getKey());
        
        return list;
    }
}

因為一開始沒有注意到Map.Entry這個的存在,想要在優先佇列中存放鍵值對可是不知道使用什麼資料結構,之後看了結題報告才明白,所以要好好熟悉資料結構。

Map.Entry

對映項(鍵-值對)。Map.entrySet 方法返回對映的 collection 檢視,其中的元素屬於此類。獲得對映項引用的唯一 方法是通過此 collection 檢視的迭代器來實現。這些 Map.Entry 物件 在迭代期間有效;更確切地講,如果在迭代器返回項之後修改了底層對映,則某些對映項的行為是不確定的,除了通過 setValue 在對映項上執行操作之外。