leetcode 前 K 个高频元素Java

题干

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

示例 2:

输入: nums = [1], k = 1
输出: [1]

说明:

你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。

想法

找K频率的元素,是经典的hashmap的用法。
O(n log n) 是在暗示使用堆

补充

在这儿使用 PriorityQueue的方法:
下方代码分别实现了大顶堆,小顶堆。其中小顶堆是默认的compare方法,大顶堆是重写了compare方法

PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(); //小顶堆,默认容量为11
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>(){ //大顶堆,容量11
    @Override
    public int compare(Integer i1,Integer i2){
        return i2-i1;
    }
});

这个compare方法几乎是使用优先队列时必重写的方法,这个方法叫匿名实现比较器,也就是这个优先队列默认是通过队列里的数的大小从小到大排序的。如果想要其他的排序方式就需要重写这个compare方法。
以下是
PriorityQueue的常用方法有:
poll(),offer(Object),size(),peek()等。

啊插入方法(offer()、poll()、remove() 、add() 方法)时间复杂度为O(log(n)) ;
remove(Object) 和 contains(Object) 时间复杂度为O(n);
检索方法(peek、element 和 size)时间复杂度为常量。

PriorityQueue的API文档说明:

构造方法摘要

PriorityQueue() 
          使用默认的初始容量(11)创建一个 PriorityQueue,并根据其自然顺序对元素进行排序。
PriorityQueue(Collection<? extends E> c) 
          创建包含指定 collection 中元素的 PriorityQueue。
PriorityQueue(int initialCapacity) 
          使用指定的初始容量创建一个 PriorityQueue,并根据其自然顺序对元素进行排序。
PriorityQueue(int initialCapacity, Comparator<? super E> comparator) 
          使用指定的初始容量创建一个 PriorityQueue,并根据指定的比较器对元素进行排序。
PriorityQueue(PriorityQueue<? extends E> c) 
          创建包含指定优先级队列元素的 PriorityQueue。
PriorityQueue(SortedSet<? extends E> c) 
          创建包含指定有序 set 元素的 PriorityQueue。
方法摘要
booleanadd(E e) 将指定的元素插入此优先级队列。
voidclear() 从此优先级队列中移除所有元素。
Comparator<? superE>comparator() 返回用来对此队列中的元素进行排序的比较器;如果此队列根据其元素的自然顺序进行排序,则返回 null。
booleancontains(Object o) 如果此队列包含指定的元素,则返回 true。
Iteratoriterator() 返回在此队列中的元素上进行迭代的迭代器。
booleanoffer(E e) 将指定的元素插入此优先级队列。
Epeek() 获取但不移除此队列的头;如果此队列为空,则返回 null。
Epoll() 获取并移除此队列的头,如果此队列为空,则返回 null。
booleanremove(Object o) 从此队列中移除指定元素的单个实例(如果存在)。
intsize() 返回此 collection 中的元素数。
Object[]toArray() 返回一个包含此队列所有元素的数组。
T[]toArray(T[] a) 返回一个包含此队列所有元素的数组;返回数组的运行时类型是指定数组的类型。

从类 java.util.AbstractQueue 继承的方法
addAll, element, remove

从类 java.util.AbstractCollection 继承的方法
containsAll, isEmpty, removeAll, retainAll, toString

从类 java.lang.Object 继承的方法
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait,wait

从接口 java.util.Collection 继承的方法
containsAll, equals, hashCode, isEmpty, removeAll, retainAll

Java的Map中的map.keySet()方法

该方法返回map中所有key值的列表。
参考https://blog.csdn.net/qq_30507287/article/details/80488512

代码

class Solution {
    public List<Integer> topKFrequent(int[] nums, int k) {
          if(nums==null || nums.length == 0)
            return new ArrayList();
        
        // 使用HashMap,统计每个元素出现的次数,元素为键,元素出现的次数为值
        HashMap<Integer,Integer> map = new HashMap();
        for(int num : nums){
            if (map.containsKey(num)) {
                //重复出现
                map.put(num, map.get(num) + 1);
            } else {
                map.put(num, 1);
            }
        }
       
        // 遍历map,用最小堆保存频率最大的k个元素
        PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer a, Integer b) {
                return map.get(a) - map.get(b);
            }
        });
        //如果pq还没被装满,那么直接装,装满了如果现在取到的这个元素比pq的最小值大,那么就换掉它
        for (Integer key : map.keySet()) {
            if (pq.size() < k) {
                pq.add(key);
            } else if (map.get(key) > map.get(pq.peek())) {
                pq.poll();
                pq.add(key);
            }
        }
        // 取出最小堆中的元素
        List<Integer> res = new ArrayList<>();
        while (!pq.isEmpty()) {
            res.add(pq.poll());
        }
        return res;
    }
}

代码参考
https://www.cnblogs.com/yanhowever/p/11649479.html

大佬代码

class Solution {
    public List<Integer> topKFrequent(int[] nums, int k) {
        if(nums==null || nums.length == 0)
            return new ArrayList();
                 ArrayList<Integer> countList = new ArrayList<Integer>();

        List<Integer> res = new ArrayList();
         HashMap<Integer,ArrayList<Integer>> map = new HashMap<Integer,ArrayList<Integer>>();
         if (nums.length == 1) {
             res.add(nums[0]);
             return res;
         } 
         
         Arrays.sort(nums);
         
         int count = 1;
         int start = nums[0];
         for(int i = 1; i < nums.length; i++) {       
             if (start != nums[i]) {
                 
                 ArrayList<Integer> itemList = map.get(count);
                 if (itemList == null) {
                     countList.add(count);
                     ArrayList<Integer> numberList = new ArrayList<Integer>();
                     numberList.add(start);
                     map.put(count, numberList);
                 } else {
                     itemList.add(start);
                 }
                 start = nums[i];
                 count = 0;
             }
             count ++;
         }
         ArrayList<Integer> itemList = map.get(count);
         if (itemList == null) {
             countList.add(count);
             ArrayList<Integer> numberList = new ArrayList<Integer>();
             numberList.add(start);
             map.put(count, numberList);
         } else {
             itemList.add(start);
         }
        countList.sort(null);
        int idx = countList.size() - 1;
        while(k>0){
            for(int j: map.get(countList.get(idx))){
                res.add(j);
                k--;
                if(k<=0)
                    break;
            }
            idx--;
        }
            
        return res;
    }
    

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值