Leetcode 题解 -- 排序--桶排序

[LeetCode] 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个高频的数字,那么对于这类的统计数字的问题,首先应该考虑用HashMap来做,建立数字和其出现次数的映射,然后再按照出现次数进行排序。我们可以用堆排序来做,使用一个最大堆来按照映射次数从大到小排列,在C++中使用priority_queue来实现,默认是最大堆,参见代码如下:

最大堆

PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>(){
            public int compare(Integer a, Integer b){
                return b-a;
            }
        });

 最小堆

public int findKthLargest(int[] nums, int k) {
    PriorityQueue<Integer> pq = new PriorityQueue<>(); // 小顶堆
    for (int val : nums) {
        pq.add(val);
        if (pq.size() > k)  // 维护堆的大小为 K
            pq.poll();
    }
    return pq.peek();
}

当然,既然可以使用最大堆,还有一种可以自动排序的数据结构TreeMap,也是可以的,这里就不写了,因为跟上面的写法基本没啥区别,就是换了一个数据结构。

我们还可以使用桶排序,在建立好数字和其出现次数的映射后,我们按照其出现次数将数字放到对应的位置中去,这样我们从桶的后面向前面遍历,最先得到的就是出现次数最多的数字,我们找到k个后返回即可,参见代码如下:

解法二:

class Solution {
    public List<Integer> topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> mp = new HashMap<>();
        for(int num : nums){
            mp.put(num, mp.getOrDefault(num,0) + 1);
        }
        List<Integer>[] bucket = new ArrayList[nums.length + 1];
        for(int key : mp.keySet()){
            int frequence  = mp.get(key);
            if(bucket[frequence] == null)
                bucket[frequence] = new ArrayList<>();
            bucket[frequence].add(key); 
        }
        List<Integer> topk = new ArrayList<>();
        for(int i=bucket.length-1; i >=0 && topk.size() < k; i--){
            if(bucket[i] == null)
                continue;
            if(bucket[i].size() <= (k - topk.size()))
                topk.addAll(bucket[i]);
            else
                topk.addAll(bucket[i].subList(0,k-topk.size()));
        }
        return topk;
    }
}

 按照字符出现次数对字符串排序

class Solution {
    public String frequencySort(String s) {
        Map<Character, Integer> mp = new HashMap<>();
        for(char num : s.toCharArray()){
            mp.put(num, mp.getOrDefault(num,0) + 1);
        }
        List<Character>[] bucket = new ArrayList[s.length() + 1];
        for(char key : mp.keySet()){
            int frequence = mp.get(key);
            if(bucket[frequence] == null)
                bucket[frequence] = new ArrayList<>();
            bucket[frequence].add(key); 
        }
        StringBuilder sb = new StringBuilder();
        for(int i = bucket.length-1; i >= 1; i--){ //大小记得减回来 
            if(bucket[i] == null)
                continue;
            for(char c : bucket[i]){//jizhu这里每个bucket是个arrayList,也是个list
                for(int j = i; j >=1; j--)
                    sb.append(c);
            }
                
        }
        return sb.toString();
    }
}
    

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值