zoukankan      html  css  js  c++  java
  • [LeetCode] 347. Top K Frequent Elements 前K个高频元素

    Given a non-empty array of integers, return the k most frequent elements.

    Example 1:

    Input: nums = [1,1,1,2,2,3], k = 2
    Output: [1,2]
    

    Example 2:

    Input: nums = [1], k = 1
    Output: [1]

    Note:

    • You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
    • Your algorithm's time complexity must be better than O(n log n), where n is the array's size.

    给一个非空整数数组,返回前k个频率最高的元素。k总是合理的,1 ≤k1 ≤独立元素的数量。要求算法时间复杂度必须优于O(n log n),n是数组长度。

    解法1: 桶排序Bucket Sort, Time: O(n), Space: O(n)

    1. 遍历数组nums,利用Hash map统计每个数字出现的次数。
    2. 遍历map,初始化一个行数为len(nums) + 1的二维数组,将出现次数为i ( i∈[1, n] )的所有数字加到第i行。
    3. 逆序遍历二维数组(从频率高的开始),将其中的前k行的元素输出。

    解法2:快排Quick select, Time: O(n) ~ O(n^2), O(n) on average. Space: O(n)

    解法3: 最大堆max heap,Time: O(n * log k),其中k为独立元素的个数, Space: O(n)。

    1. 先用Hash map统计所有数字出现的次数。

    2. 建立一个大小为k的最大堆max heap,遍历map,将出现次数和数字组成的pair推到heap中,堆顶为出现次数最多的pair,遍历结束后,把heap中的元素从堆顶一个个的取出即可。

    解法4:利用Java中的TreeMap, Tree map是一个有序的key-value集合,它是通过红黑树实现的。利用map可统计,又是按key排序的。

    Java: Bucket Sort

    public List<Integer> topKFrequent(int[] nums, int k) {
    
    	List<Integer>[] bucket = new List[nums.length + 1];
    	Map<Integer, Integer> frequencyMap = new HashMap<Integer, Integer>();
    
    	for (int n : nums) {
    		frequencyMap.put(n, frequencyMap.getOrDefault(n, 0) + 1);
    	}
    
    	for (int key : frequencyMap.keySet()) {
    		int frequency = frequencyMap.get(key);
    		if (bucket[frequency] == null) {
    			bucket[frequency] = new ArrayList<>();
    		}
    		bucket[frequency].add(key);
    	}
    
    	List<Integer> res = new ArrayList<>();
    
    	for (int pos = bucket.length - 1; pos >= 0 && res.size() < k; pos--) {
    		if (bucket[pos] != null) {
    			res.addAll(bucket[pos]);
    		}
    	}
    	return res;
    }  

    Java: Solution 1

    public List<Integer> topKFrequent(int[] nums, int k) {
        //count the frequency for each element
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        for(int num: nums){
            if(map.containsKey(num)){
                map.put(num, map.get(num)+1);
            }else{
                map.put(num, 1);
            }
        }
     
        //get the max frequency
        int max = 0;
        for(Map.Entry<Integer, Integer> entry: map.entrySet()){
            max = Math.max(max, entry.getValue());
        }
     
        //initialize an array of ArrayList. index is frequency, value is list of numbers
        ArrayList<Integer>[] arr = (ArrayList<Integer>[]) new ArrayList[max+1];
        for(int i=1; i<=max; i++){
            arr[i]=new ArrayList<Integer>();
        }
     
        for(Map.Entry<Integer, Integer> entry: map.entrySet()){
            int count = entry.getValue();
            int number = entry.getKey();
            arr[count].add(number);
        }
     
        List<Integer> result = new ArrayList<Integer>();
     
        //add most frequent numbers to result
        for(int j=max; j>=1; j--){
            if(arr[j].size()>0){
                for(int a: arr[j]){
                    result.add(a);
                    //if size==k, stop
                    if(result.size()==k){
                        break;
                    }
                }
            }
        }
     
        return result;
    }
    

    Java: Heap

    class Pair{
        int num;
        int count;
        public Pair(int num, int count){
            this.num=num;
            this.count=count;
        }
    }
     
    public class Solution {
        public List<Integer> topKFrequent(int[] nums, int k) {
            //count the frequency for each element
            HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
            for(int num: nums){
                if(map.containsKey(num)){
                    map.put(num, map.get(num)+1);
                }else{
                    map.put(num, 1);
                }
            }
     
            // create a min heap
            PriorityQueue<Pair> queue = new PriorityQueue<Pair>(new Comparator<Pair>(){
                public int compare(Pair a, Pair b){
                    return a.count-b.count;
                }
            });
     
            //maintain a heap of size k. 
            for(Map.Entry<Integer, Integer> entry: map.entrySet()){
                Pair p = new Pair(entry.getKey(), entry.getValue());
                queue.offer(p);
                if(queue.size()>k){
                    queue.poll();
                }
            }
     
            //get all elements from the heap
            List<Integer> result = new ArrayList<Integer>();
            while(queue.size()>0){
                result.add(queue.poll().num);
            }
            //reverse the order
            Collections.reverse(result);
     
            return result;
        }
    }

    Java:

    // use treeMap. Use freqncy as the key so we can get all freqencies in order
    public class Solution {
        public List<Integer> topKFrequent(int[] nums, int k) {
            Map<Integer, Integer> map = new HashMap<>();
            for(int n: nums){
                map.put(n, map.getOrDefault(n,0)+1);
            }
            
            TreeMap<Integer, List<Integer>> freqMap = new TreeMap<>();
            for(int num : map.keySet()){
               int freq = map.get(num);
               if(!freqMap.containsKey(freq)){
                   freqMap.put(freq, new LinkedList<>());
               }
               freqMap.get(freq).add(num);
            }
            
            List<Integer> res = new ArrayList<>();
            while(res.size()<k){
                Map.Entry<Integer, List<Integer>> entry = freqMap.pollLastEntry();
                res.addAll(entry.getValue());
            }
            return res;
        }
    } 

    Python: Solution 1

    class Solution(object):
        def topKFrequent(self, nums, k):
            """
            :type nums: List[int]
            :type k: int
            :rtype: List[int]
            """
            n = len(nums)
            cntDict = collections.defaultdict(int)
            for i in nums:
                cntDict[i] += 1
            freqList = [[] for i in range(n + 1)]
            for p in cntDict:
                freqList[cntDict[p]] += p,
            ans = []
            for p in range(n, 0, -1):
                ans += freqList[p]
            return ans[:k]
    

    Python: Solution 1

    class Solution(object):
        def topKFrequent(self, nums, k):
            """
            :type nums: List[int]
            :type k: int
            :rtype: List[int]
            """
            counts = collections.Counter(nums)
            buckets = [[] for _ in xrange(len(nums)+1)]
            for i, count in counts.iteritems():
                buckets[count].append(i)
                
            result = []
            for i in reversed(xrange(len(buckets))):
                for j in xrange(len(buckets[i])):
                    result.append(buckets[i][j])
                    if len(result) == k:
                        return result
            return result  

    Python: Quick Select Solution

    # Time:  O(n) ~ O(n^2), O(n) on average.
    # Space: O(n)
    from random import randint
    class Solution(object):
        def topKFrequent(self, nums, k):
            """
            :type nums: List[int]
            :type k: int
            :rtype: List[int]
            """
            counts = collections.Counter(nums)
            p = []
            for key, val in counts.iteritems():
                p.append((-val, key))
            self.kthElement(p, k)
    
            result = []
            for i in xrange(k):
                result.append(p[i][1])
            return result
    
        def kthElement(self, nums, k):
            def PartitionAroundPivot(left, right, pivot_idx, nums):
                pivot_value = nums[pivot_idx]
                new_pivot_idx = left
                nums[pivot_idx], nums[right] = nums[right], nums[pivot_idx]
                for i in xrange(left, right):
                    if nums[i] < pivot_value:
                        nums[i], nums[new_pivot_idx] = nums[new_pivot_idx], nums[i]
                        new_pivot_idx += 1
    
                nums[right], nums[new_pivot_idx] = nums[new_pivot_idx], nums[right]
                return new_pivot_idx
    
            left, right = 0, len(nums) - 1
            while left <= right:
                pivot_idx = randint(left, right)
                new_pivot_idx = PartitionAroundPivot(left, right, pivot_idx, nums)
                if new_pivot_idx == k - 1:
                    return
                elif new_pivot_idx > k - 1:
                    right = new_pivot_idx - 1
                else:  # new_pivot_idx < k - 1.
                    left = new_pivot_idx + 1  

    Python: Heap

    import collections
    import heapq
    
    class Solution(object):
        def topKFrequent(self, nums, k):
            """
            :type nums: List[int]
            :type k: int
            :rtype: List[int]
            """
            counts = collections.Counter(nums)
            heap = []
            for key, cnt in counts.items():
                if len(heap) < k:
                    heapq.heappush(heap, (cnt, key))
                else:
                    if heap[0][0] < cnt:
                        heapq.heappop(heap)
                        heapq.heappush(heap, (cnt, key))
            return [x[1] for x in heap]   

    Python: Solution 2, most_common实现了heapq(堆)模块

    class Solution(object):
        def topKFrequent(self, nums, k):
            """
            :type nums: List[int]
            :type k: int
            :rtype: List[int]
            """
            c = collections.Counter(nums)
            return [x[0] for x in c.most_common(k)]
    

    Python: Solution 2

    class Solution3(object):
        def topKFrequent(self, nums, k):
            """
            :type nums: List[int]
            :type k: int
            :rtype: List[int]
            """
            return [key for key, _ in collections.Counter(nums).most_common(k)]
    

    C++: Solutoin 1

    class Solution {
    public:
        vector<int> topKFrequent(vector<int>& nums, int k) {
            unordered_map<int, int> m;
            vector<vector<int>> bucket(nums.size() + 1);
            vector<int> res;
            for (auto a : nums) ++m[a];
            for (auto it : m) {
                bucket[it.second].push_back(it.first);
            }
            for (int i = nums.size(); i >= 0; --i) {
                for (int j = 0; j < bucket[i].size(); ++j) {
                    res.push_back(bucket[i][j]);
                    if (res.size() == k) return res;
                }
            }
            return res;
        }
    };
    

    C++: Solution 2

    class Solution {
    public:
        vector<int> topKFrequent(vector<int>& nums, int k) {
            unordered_map<int, int> m;
            priority_queue<pair<int, int>> q;
            vector<int> res;
            for (auto a : nums) ++m[a];
            for (auto it : m) q.push({it.second, it.first});
            for (int i = 0; i < k; ++i) {
                res.push_back(q.top().second); q.pop();
            }
            return res;
        }
    };

    类似题目:

    [LeetCode] 215. Kth Largest Element in an Array 数组中第k大的元素

    [LeetCode] 192. Word Frequency 词频

    [LeetCode] 692. Top K Frequent Words 前K个高频单词

    All LeetCode Questions List 题目汇总

  • 相关阅读:
    spring aop实现数据库的读写分离
    MySQL主从复制(Master-Slave)实践
    java 注解 Annontation
    java NIO介绍
    为什么你学不会递归?告别递归,谈谈我的一些经验(转)
    maven的安装、路径配置、修改库文件路径和eclipse中的配置、创建maven工程(转)
    Eclipse中创建Maven多模块工程
    Eclipse的Working Set管理项目
    Java使用POI读取和写入Excel指南(转)
    Webpack安装和命令
  • 原文地址:https://www.cnblogs.com/lightwindy/p/8674041.html
Copyright © 2011-2022 走看看