leetcode(前K个高频元素集)

leetcode-347:前K个高频元素集
描述:
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
思路:

  • 本题是优先队列的经典问题(在1000000个元素中选出前100名),即在N个元素中选出前k个元素
  • 用排序的话,算法复杂度是NlogN
  • 使用优先队列,算法复杂度是Nlogk
    使用优先队列,维护当前看到的前k个元素,需要使用最小堆

先给出最开始的代码,然后一步步优化:
(1)先用之前自定义的优先队列来实现:

import java.util.LinkedList;
import java.util.List;
import java.util.TreeMap;

public class Solution {
    private class Freq implements Comparable<Freq> {
        int e, fre;
        public Freq(int e, int fre) {
            this.e = e;
            this.fre = fre;
        }

        @Override
        public int compareTo(Freq another) {//定义优先级,频次越低,优先级越高
            if(this.fre < another.fre) {
                return 1;
            } else if(this.fre > another.fre) {
                return -1;
            } else {
                return 0;
            }
        }
    }

    public List<Integer> topKFrequent(int[] nums, int k) {
        //统计频次
        TreeMap<Integer, Integer> map = new TreeMap<>();
        for(int num : nums) {
            if(map.containsKey(num)) {
                map.put(num, map.get(num) + 1);
            } else {
                map.put(num, 1);
            }
        }
        //维护当前看到的前K个元素
        PriorityQueue<Freq> pq = new PriorityQueue<>();
        for(int key : map.keySet()) {
            if(pq.getSize() < k) {
                pq.enqueue(new Freq(key, map.get(key)));
            } else if(map.get(key) > pq.getFront().fre) {
                pq.dequeue();
                pq.enqueue(new Freq(key, map.get(key)));
            }
        }
        LinkedList<Integer> res = new LinkedList<>();
        while (!pq.isEmpty()) {
            res.add(pq.dequeue().e);
        }
        return res;
    }
}

(2)用Java的优先队列(注意Java优先级队列底层默认是最小堆

import java.util.*;
class Solution {
    public class Freq implements Comparable<Freq> {
        int e, freq;
        public Freq(int e, int freq) {
            this.e = e;
            this.freq = freq;
        }
        @Override
        public int compareTo(Freq another) {//定义优先级
            if(this.freq > another.freq) {
                return 1;
            } else if(this.freq < another.freq) {
                return -1;
            } else {
                return 0;
            }
        }
    }
    public List<Integer> topKFrequent(int[] nums, int k) {
        //统计频次
        TreeMap<Integer, Integer> map = new TreeMap<>();
        for(int num : nums) {
            if(map.containsKey(num)) {
                map.put(num, map.get(num) + 1);
            } else {
                map.put(num, 1);
            }
        }
        //维护当前看到的前k个出现频次最高的元素
        PriorityQueue<Freq> pq = new PriorityQueue<>();
        for(int key : map.keySet()) {
            if(pq.size() < k) {
                pq.add(new Freq(key, map.get(key)));
            } else if(map.get(key) > pq.peek().freq) {
                pq.remove();
                pq.add(new Freq(key, map.get(key)));
            }
        }
        
        LinkedList<Integer> res = new LinkedList<>();
        while(!pq.isEmpty()) {
            res.add(pq.remove().e);
        }
        return res;
        
    }
}

(3)用比较器来简化代码:

import java.util.*;
class Solution {
    public class Freq {
        int e, freq;
        public Freq(int e, int freq) {
            this.e = e;
            this.freq = freq;
        }
    }
     
    public class FreComparator implements Comparator<Freq> {//定义优先级
        public int compare(Freq a, Freq b) {
            return a.freq - b.freq;
        }
    }
    public List<Integer> topKFrequent(int[] nums, int k) {
        //统计频次
        TreeMap<Integer, Integer> map = new TreeMap<>();
        for(int num : nums) {
            if(map.containsKey(num)) {
                map.put(num, map.get(num) + 1);
            } else {
                map.put(num, 1);
            }
        }
        //维护当前看到的前k个出现频次最高的元素
        PriorityQueue<Freq> pq = new PriorityQueue<>(new FreComparator());
        for(int key : map.keySet()) {
            if(pq.size() < k) {
                pq.add(new Freq(key, map.get(key)));
            } else if(map.get(key) > pq.peek().freq) {
                pq.remove();
                pq.add(new Freq(key, map.get(key)));
            }
        }
        
        LinkedList<Integer> res = new LinkedList<>();
        while(!pq.isEmpty()) {
            res.add(pq.remove().e);
        }
        return res;
    }
}

(4)用匿名类进一步简化代码:

import java.util.*;
class Solution {
    public List<Integer> topKFrequent(int[] nums, int k) {
        //统计频次
        TreeMap<Integer, Integer> map = new TreeMap<>();
        for(int num : nums) {
            if(map.containsKey(num)) {
                map.put(num, map.get(num) + 1);
            } else {
                map.put(num, 1);
            }
        }
        //维护当前看到的前k个出现频次最高的元素
        PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>() {
            public int compare(Integer a, Integer b) {
                return map.get(a) - map.get(b);
            }
        });
        for(int key : map.keySet()) {
            if(pq.size() < k) {
                pq.add(key);
            } else if(map.get(key) > map.get(pq.peek())) {
                pq.remove();
                pq.add(key);
            }
        }
        
        LinkedList<Integer> res = new LinkedList<>();
        while(!pq.isEmpty()) {
            res.add(pq.remove());
        }
        return res;        
    }
}

(5)用lambda函数进一步简化代码:

import java.util.*;
class Solution {
    public List<Integer> topKFrequent(int[] nums, int k) {
        //统计频次
        TreeMap<Integer, Integer> map = new TreeMap<>();
        for(int num : nums) {
            if(map.containsKey(num)) {
                map.put(num, map.get(num) + 1);
            } else {
                map.put(num, 1);
            }
        }
        //维护当前看到的前k个出现频次最高的元素
        PriorityQueue<Integer> pq = new PriorityQueue<>(
            (a, b) -> map.get(a) - map.get(b)
        );
        for(int key : map.keySet()) {
            if(pq.size() < k) {
                pq.add(key);
            } else if(map.get(key) > map.get(pq.peek())) {
                pq.remove();
                pq.add(key);
            }
        }
        
        LinkedList<Integer> res = new LinkedList<>();
        while(!pq.isEmpty()) {
            res.add(pq.remove());
        }
        return res;      
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值