leetcode-pp / 91alg-6-daily-check

91 算法第六期打卡仓库
28 stars 0 forks source link

【Day 20 】2021-12-31 - 347. 前 K 个高频元素 #27

Open azl397985856 opened 2 years ago

azl397985856 commented 2 years ago

347. 前 K 个高频元素

入选理由

暂无

题目地址

https://leetcode-cn.com/problems/top-k-frequent-elements/

前置知识

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

示例 2:

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

提示:

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/top-k-frequent-elements 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

wangzehan123 commented 2 years ago

思路

关键点

代码

Java Code:



class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer,Integer> map =new HashMap<>();
        int len = nums.length;
        int maxCount=1;
        for(int i=0;i<len;i++){
            int count = map.getOrDefault(nums[i],0)+1;
            if(count>maxCount){
                maxCount = count;
            }
            map.put(nums[i],count);
        }
        List<List<Integer>> list = new ArrayList<>(maxCount+1);
        for(int i=0;i<maxCount+1;i++){
            List<Integer> l = new ArrayList<>();
            list.add(l);
        }

        //遍历map,放到list中
        for(Integer key:map.keySet()){
           Integer count = map.get(key);
           List<Integer> mid = list.get(count);
           mid.add(key);
        }
        //从数组的后面开始遍历取k个
        int[] res = new int[k];
        int index=0;
        for(int i=maxCount;i>=0;i--){
            if(index>=k){
                break;
            }
            List<Integer> items = list.get(i);
            if(!items.isEmpty()){//说明有值
                for(Integer item:items){
                    res[index++]=item;
                }
            }
        }
        return res;
    }
}
qihang-dai commented 2 years ago

Map和桶数字开销 Space O(N), 桶排序开销还是Time O(N)遍历.

就这个机会把所有的排序看了一遍,总算会了点。

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap();
        for(int n : nums){
            map.put(n, map.getOrDefault(n, 0) + 1);
        }

        List[] buckets = new List[nums.length + 1];
        for(Map.Entry<Integer,Integer> entry : map.entrySet()){
            int val = entry.getValue();
            if(buckets[val] == null){
                buckets[val] = new ArrayList();
            }
            buckets[val].add(entry.getKey());
        }

        int[] res = new int[k];
        int id = 0;

        for(int i = buckets.length - 1; i > 0; i --){
            if(buckets[i] != null){
                for(int j = 0; j < buckets[i].size(); j++){
                    res[id++] = (int) buckets[i].get(j);
                    if(id == k) return res;
                }
            }
        }

        return res;
    }
}
Alexno1no2 commented 2 years ago
# 题解
# 1.创建一个字典,遍历数组将数组中元素出现次数记录到字典中
# 2.将字典转化为列表l,对列表l按照频次进行排序
# 3.把排序列表的前k个数字放到列表res并返回

# 复杂度分析
# 时间复杂度O(nlogn),空间复杂度O(n)

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        dict = {}
        for i in range(len(nums)):
            if nums[i] not in dict:
                dict[nums[i]] = 1
            else:
                dict[nums[i]] += 1

        l = list(dict.items())
        sorted_l = sorted(l,key = lambda x:x[1],reverse = True)
        res = []
        for i in range(k):
            res.append(sorted_l[i][0])
        return res
Tesla-1i commented 2 years ago
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        count = {}
        # empty array with the size of nums + 1
        frequency = [[] for i in range(len(nums) + 1)]

        # count each value, if not exist, set to default 0
        for n in nums:
            count[n] = 1 + count.get(n, 0)

        # going through each counted value
        for n, c in count.items():
            frequency[c].append(n) # the value n appears c times

        res = []
        # find most frequent value
        for i in range(len(frequency) - 1, 0, -1): # start from last element to 0, step is -1
            for n in frequency[i]: # go through every value in index i
                res.append(n)
                if len(res) == k:
                    return res 
spacker-343 commented 2 years ago

思路

因为是统计频率最高的 K 个元素,所以使用 map 统计下每个元素在数组中的出现频率,然后维护一个 k 个大小的小根堆,往小根堆中添加了元素后,如果此时小根堆大小超过 k 了,那么就移除堆顶元素

代码

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }

        // 根据map的value值排序
        PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((a, b) -> {
            return a.getValue() - b.getValue();
        });
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            queue.add(entry);
            if (queue.size() > k) {
                queue.poll();
            }
        }

        int[] result = new int[k];
        for (int i = 0; i < result.length; i++) {
            result[i] = queue.poll().getKey();
        }
        return result;
    }
}

复杂度

时间复杂度: O(nlogK) 空间复杂度: O(n)

charlestang commented 2 years ago

思路

  1. 先用一个 哈希,统计出所有元素的频次。
  2. 使用一个大小为 K 的最小堆,然后求出频次最高的 K 个元素。

代码

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        return [x[0] for x in Counter(nums).most_common(k)

时间复杂度 Python 的 Counter 是字典 dict 的子类,所以插入字典统计频次的复杂度是 O(n)。Counter 的 most_common 内部实现是 heapq 的 nlargest,本质上就是用的最小堆。所以总和时间复杂度是 O(n logn)。空间复杂度 O(n)

now915 commented 2 years ago

map收集频率, 排序

var topKFrequent = function(nums, k) {
  let result = []
  let keyMaps = new Map()
  nums.forEach(element => {
    keyMaps.set(element, (keyMaps.get(element) || 0) + 1)
  });
  keyMaps.forEach((val, key) => {
    result.push({
      key,
      val
    })
  })
  result.sort((a, b) => b.val - a.val)
  let res = []
  for (let index = 0; index < k; index++) {
    res.push(result[index].key)
  }
  return res
};
ZZRebas commented 2 years ago

思路

构建一个字典,其值都为0,然后遍历数组,用字典进行计数,返回字典value最大的前k个key。

代码(Python)

def fun(nums,k):
    nums_dict=dict.fromkeys(set(nums),0)
    for i in nums:
        nums_dict[i]+=1
    print(nums_dict)
    a=list(nums_dict.values())
    a.sort()
    a.reverse()
    res=[]
    for key,v in nums_dict.items():
        if v in a[:k]:
            res.append(key)
    return res
nums = [1,1,1,2,2,3]
k = 2
print(fun(nums,k))

复杂度分析

Tao-Mao commented 2 years ago

Code

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int i=0; i<nums.length; ++i) {
            map.put(nums[i],map.getOrDefault(nums[i],0)+1);
        }
        System.out.println(map);
        List<Integer>[] bucket = new List[nums.length+1];
        // int[] a = new int[10];
        for (int key : map.keySet()){
            int freq = map.get(key);
            if (bucket[freq] == null) {
                bucket[freq] = new LinkedList<>();
            }
            bucket[freq].add(key);
        }
        int[] res = new int[k];
        int m = 0;
        for (int j = nums.length; j > 0; --j) {
            if (bucket[j] != null) {
                for (int val:bucket[j]) {
                    // System.out.println(val);
                    if (m == k) {
                        return res;
                    }
                    res[m] =val;
                    ++m;
                }
            }
            // if (res[k] )
        }
        // res.
        return res;
    }
}
ywang525 commented 2 years ago

class Solution: def topKFrequent(self, nums: List[int], k: int) -> List[int]: dict = {}

    for i in nums:
        if i not in dict:
            dict[i] = 1
        else:
            dict[i] += 1
    res = sorted(dict.keys(), key = lambda x: dict[x])
    fin = []
    while k>0:
        fin.append(res.pop())
        k-=1
    return fin
GaoMinghao commented 2 years ago

思路

先用HashMap统计,再排序

代码

class Solution {
    public class Compo{
        int value;
        int count;
        Compo(int value, int count) {
            this.value = value;
            this.count = count;
        }
    }
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> counts = new HashMap<>();
        for(int i:nums) {
            counts.merge(i, 1, Integer::sum);
        }
        List<Compo> compos = new ArrayList<>();
        for(Map.Entry<Integer,Integer> entry:counts.entrySet()) {
            compos.add(new Compo(entry.getKey(),entry.getValue()));
        }
        compos.sort(new Comparator<Compo>() {
            @Override
            public int compare(Compo o1, Compo o2) {
                return o2.count - o1.count;
            }
        });
        int[] result = new int[k];
        int i = 0;
        for(Compo compo:compos) {
            if(i < k) {
                result[i] = compo.value;
                i++;
            } else {
                break;
            }
        }
        return result;
    }
}

复杂度

时间复杂度O(NLogN) 空间复杂度O(N)

ginnydyy commented 2 years ago

Problem

https://leetcode.com/problems/top-k-frequent-elements/

Note

Solution

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        if(nums == null || nums.length == 0){
            return new int[]{};
        }

        Map<Integer, Integer> map = new HashMap<>();
        for(int num: nums){
            map.put(num, map.getOrDefault(num, 0) + 1);
        }

        PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> map.get(a) - map.get(b));
        for(int key: map.keySet()){
            if(pq.size() != k){
                pq.offer(key);
            }else if(map.get(key) > map.get(pq.peek())){
                pq.poll();
                pq.offer(key);
            }
        }

        int[] res = new int[k];
        for(int i = 0; i < k; i++){
            res[i] = pq.poll();
        }

        return res;
    }
}

Complexity

jiaqiliu37 commented 2 years ago
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        hashmap = defaultdict(int)
        for i in range(len(nums)):
            hashmap[nums[i]] += 1

        heap = []
        for num, freq in hashmap.items():
            heapq.heappush(heap, (freq, num))
            if len(heap) > k:
                heapq.heappop(heap)

        return [num for freq, num in heap]

Time complexity O(NlogK) Space complexity O(N)

aladingzl commented 2 years ago

思路

利用 map

代码

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function(nums, k) {
    let map = new Map(), arr = [...new Set(nums)];
    nums.map((num) => {
        if(map.has(num)) {
            map.set(num, map.get(num) + 1);
        } else {
            map.set(num, 1);
        }
    })
    return arr.sort((a, b) => map.get(b) - map.get(a)).slice(0, k);

};

复杂度分析

junbuer commented 2 years ago

思路

代码

# 哈希表计数+排序
class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        cnt = Counter(nums)
        order = sorted(cnt.items(), key=lambda x:x[1], reverse=True)
        return [x[0] for x in order[0 : k]]
# 桶排序
class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        cnt = Counter(nums)
        bucket = [[]  for i in range(len(nums) + 1)]
        for key in cnt.keys():
            bucket[cnt[key]].append(key)
        res = []
        for i in range(len(nums), -1, -1):
            if not k:
                return res
            if bucket[i]:
                for j in bucket[i]:
                    res.append(j)
                    k -= 1    

复杂度分析

biscuit279 commented 2 years ago

思路:哈希表存频率

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        fre_dict = {}
        ans = []
        for num in nums:
            if num not in fre_dict:
                fre_dict[num] = 1
            fre_dict[num] += 1 
        sorted_dict = sorted(fre_dict.items(), key = lambda x:x[1], reverse = True)
        print(sorted_dict)
        for i in range(k):
            ans.append(sorted_dict[i][0])
        return ans

时间复杂度:O(N) 空间复杂度:O(N)

falconruo commented 2 years ago

思路:

  1. 使用hashmap存放数组的值和frequency
  2. 按照frequency由大到小排序,取前k个返回 3 复杂度分析:
    • 时间复杂度: O(NlogN), 其中 N 为数组的长度。
    • 空间复杂度: O(N),

代码(C++):

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> freq;

        for (auto n : nums) // o(n)
            freq[n]++;

        vector<pair<int, int>> elements(freq.begin(), freq.end());

        sort(elements.begin(), elements.end(),
            [](const pair<int, int> a, const pair<int, int> b) {
                return a.second > b.second;
            }); 

        vector<int> res;

        for (auto f : elements) { // o(k)
            res.push_back(f.first);
            if (--k == 0) return res;
        }
        return {};
    }
};
testeducative commented 2 years ago

思路

hash table + heap sort

代码


class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> times;
        for(auto& num : nums)
        {
            if(times.count(num) == 0)
            {
                times[num] = 1;
            }
            else
            {
                times[num]++;
            }
        }
        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> q;
        for(auto it : times)
        {
            if(q.size() != k)
            {
                q.push(make_pair(it.second, it.first));
            }
            else
            {
                if(it.second > q.top().first)
                {
                    q.pop();
                    q.push(make_pair(it.second, it.first));
                }
            }
        }
        vector<int> res;
        while(!q.empty())
        {
            res.push_back(q.top().second);
            q.pop();
        }
        return res;
    }
};
LinnSky commented 2 years ago

思路

map记录element出现的频率, 数组排序

代码

  let topKFrequent = function(nums, k) {
    let map = new Map(), arr = [...new Set(nums)]
    nums.map(num => {
        map.set(num, map.has(num) ? map.get(num) + 1  : 1)
    })
    return arr.sort((a, b) => map.get(b) - map.get(a)).slice(0, k);
  };

复杂度分析

xjhcassy commented 2 years ago
class Solution {

    public int[] topKFrequent(int[] nums, int k) {

        List<Integer> res = new LinkedList<>();
        List<Integer>[] bucket = new List[nums.length + 1];
        Map<Integer, Integer> counter = new HashMap<>();

        for (int num: nums)
            counter.put(num, counter.getOrDefault(num, 0) + 1);

        for (Map.Entry<Integer, Integer> entry: counter.entrySet()) {
            int val = entry.getValue();
            if (bucket[val] == null)
                bucket[val] = new LinkedList<>();
            bucket[val].add(entry.getKey());
        }

        int kNum = 0;
        for (int i = bucket.length - 1; i >= 0; i--)
            if (bucket[i] != null)
                for (int elem: bucket[i]){

                    res.add(elem);
                    kNum++;
                }

        int[] ret = new int[k];
        for (int i = 0; i < ret.length; i++)
            ret[i] = res.get(i);

        return ret;
    }
}
chenyaohn commented 2 years ago

思路

哈希表保存出现次数,最小堆保存次数。遍历所有的出现次数,堆的大小超过k后,判断下一个是否大于堆顶的次数,如大于则取代其成为新的堆顶。遍历完毕后在堆中的元素即为数组前k个高频元素。

代码

public class Day20 {

    public  int[] topKFrequent(int[] nums,int k) {

        HashMap<Integer,Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            if(map.containsKey(nums[i])){
                int count = map.get(nums[i]);
                count++;
                map.put(nums[i],count);
            }else{
                map.put(nums[i],1);
            }
        }
        // System.out.println("map:"+map);

        //res[k][0]==次数 res[k][1]==值
        PriorityQueue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[0]-o2[0];
            }
        });//堆顶为最小值
        Iterator<Integer> keys = map.keySet().iterator();
        while (keys.hasNext()){
            int val = keys.next();//数组元素
            int count = map.get(val);//出现次数
            if(queue.size()<k){
                //System.out.println("小于=k:"+count+","+val);
                queue.offer(new int[]{count,val});
            }else {
                //System.out.println("大于k:"+count+","+val+",min:"+queue.peek()[0]);
                if(queue.peek()[0]<count){
                    queue.poll();
                    queue.offer(new int[]{count,val});
                }
            }
        }

        int [] res= new int[k];
        for (int i = 0; i < k; i++) {
            res[i] = queue.poll()[1];
        }

        return res;
    }
}

复杂度分析

时间复杂度:O(nlogn)
空间复杂度:O(n)

bluetomlee commented 2 years ago

思路

先用map计数,再用priority_queue pop出k个即可

实现

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;
    }
};
1916603886 commented 2 years ago

var topKFrequent = function(nums, k) { let obj = {}; let arr = []; nums.forEach((value, index) => { if (obj[value]) { obj[value]++; } else { obj[value] = 1; } }); arr = Object.entries(obj); arr.sort(function (x, y) { return y[1] - x[1]; });

let arr2 = [];
for (let i = 0; i < k; i++) {
  arr2[i] = arr[i][0];
}
return arr2;

};

niutd777 commented 2 years ago

思路:

数据整合后放入map,key为数据,value为出现次数 利用小顶堆排序,保持堆中数据数量不超过K, 堆容量小于k直接放入 大于k的时候和堆顶元素比较大小,如果大于将当前数据加入堆中 最后取出堆中数据

代码


public int[] topKFrequent(int[] nums, int k) {
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        //数据整合后放入map,key为数据,value为出现次数
        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);
            }
        }
        //利用小顶堆排序
        PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer a, Integer b) {
                return map.get(a) - map.get(b);
            }
        });
        for (Integer key : map.keySet()) {
            //维护一个k大小的堆,小于k直接放入
            if (pq.size() < k) {
                pq.add(key);
                //大于k的时候和堆顶元素比较大小 如果大于将堆首删除,加入数据
                //堆首永远是最小的
            } else if (map.get(key) > map.get(pq.peek())) {
                pq.remove();
                pq.add(key);
            }
        }
        //取出数据
        int[] result = new int[pq.size()];
        int length = pq.size();
        for (int i = 0; i < length; i++) {
            result[i] = pq.remove();
        }
        return result;
    }
**复杂度分析**
- 时间复杂度:O(Nlogk),其中 N 为数组长度,k为堆的大小。
- 空间复杂度:O(N) 
ZJP1483469269 commented 2 years ago
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        count = collections.Counter(nums)
        dp = []
        for key,val in count.items():
            heappush(dp,(-val,key))

        return [heappop(dp)[1] for _ in range(k)]
demo410 commented 2 years ago

思路

代码

 public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        int[] maxK = new int[k];

        for (int i = 0; i < nums.length; i++) {
            if (map.containsKey(nums[i])) {
                Integer count = map.get(nums[i]);
                map.put(nums[i], ++count);
            } else {
                map.put(nums[i], 0);
            }
        }

        Queue<Map.Entry<Integer, Integer>> q = new PriorityQueue<>((e1, e2) -> e2.getValue().compareTo(e1.getValue()));

        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            q.offer(entry);
        }

        for (int i = 0; i < k; i++) {
            maxK[i] = q.poll().getKey();
        }

        return maxK;
    }
frgthyju commented 2 years ago

哈希表key存储元素,val存储出现频数,小顶堆排序

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
       int[] res = new int[k];
       HashMap<Integer,Integer> m = new HashMap<>();
       for (int num:nums){
           m.put(num,m.getOrDefault(num,0)+1);
       }
       Set<Map.Entry<Integer,Integer>> entries = m.entrySet();
       PriorityQueue<Map.Entry<Integer,Integer>> q = new PriorityQueue<>((o1,o2)->o1.getValue()-o2.getValue());
       for (Map.Entry<Integer,Integer> entry:entries){
           q.offer(entry);
           if(q.size()>k){
               q.poll();
           }
       }
       for (int i=k-1;i>=0;i--){
           res[i] = q.poll().getKey();
       }
       return res;
    }
}

时间复杂度O(nlogk)

空间复杂度O(n)

tangjy149 commented 2 years ago

代码

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        vector<int> ans;
        unordered_map<int, int> helper;
        priority_queue<pair<int,int>> q;
        for(auto i:nums){
            helper[i]++;
        }
        for(auto j:helper){
            q.push(pair<int,int>(-j.second,j.first));
            if(q.size()>k){
                q.pop();
            }
        }
        while(k--){
            ans.push_back(q.top().second);
            q.pop();
        }
        return ans;
    }
};
samaritan1998 commented 2 years ago

前K个高频元素

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        if not nums:
            return []
        cnt = collections.Counter(nums)
        nums = list(cnt.items())
        def partition(nums, left, right):
            pivot=nums[left][1]
            pivotFull=nums[left]
            i,j = left,right
            while i<j:
                while(i<j and nums[j][1]>=pivot):
                    j-=1
                nums[i]=nums[j]
                while(i<j and nums[i][1]<=pivot):
                    i+=1
                nums[j]=nums[i]
            nums[i]=pivotFull
            return i

        def quickSearch(nums, left, right, k):
            idx = partition(nums, left, right)
            if idx == k:
                return [nums[i][0] for i in range(idx,len(nums))]
            elif idx < k:
                return quickSearch(nums, idx + 1, right, k)
            else:
                return quickSearch(nums, left, idx - 1, k)
        k=len(nums)-k
        return quickSearch(nums, 0, len(nums) - 1, k)
z1ggy-o commented 2 years ago

思路

利用 hashtable 来进行计数,之后按照频率进行排序即可。

一般的排序算法需要用到 nlogn 的复杂度。题目里让最好保持在 nlogn 之下。 看了题解发现,可以使用 bucket sort 来空间换时间。因为题目里不要求顺序, 所以 bucket 内的排序是不需要的,让复杂度下降到了 O(n).

代码

CPP

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> count_map; // num, frequent
        vector<vector<int>> bucket(nums.size()+1);

        for (auto &n : nums) {
            count_map[n]++;
        }

        for (auto &[k, v] : count_map) {
            bucket[v].push_back(k);
        }

        vector<int> ret;
        for (int i = bucket.size() - 1; i >=0; i--) {
            if (bucket[i].size()) {
                for (auto &n : bucket[i]) {
                    if (k) {
                        ret.push_back(n);
                        k--;
                    }
                }
            }
        }

        return ret;
    }
};

复杂度分析

Macvh commented 2 years ago

def topKFrequent(self, nums, k): """ :type nums: List[int] :type k: int :rtype: List[int] """ hashmap={} for i in nums: if i in hashmap: hashmap[i]=hashmap[i]+1 else: hashmap[i]=1 a1 = sorted(hashmap.items(),key = lambda x:x[1],reverse = True)#按照val值从大到小对哈希表排序 result=[] for key in a1: if k<=0: break result.append(key[0]) k=k-1 return result

KennethAlgol commented 2 years ago
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        // 使用字典,统计每个元素出现的次数,元素为键,元素出现的次数为值
        Map<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < nums.length; i++){
            map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
        }

        //桶排序
        //将频率作为数组下标,对于出现频率不同的数字集合,存入对应的数组下标
        List<Integer>[] list = new List[nums.length+1];
        Set<Map.Entry<Integer,Integer>> ms = map.entrySet();
        for (Map.Entry entry :ms) {
            int key = (int)entry.getKey();
            int i = map.get(key);
            if(list[i] == null){
                list[i] = new ArrayList();
            }
            list[i].add(key);
        }

        List<Integer> res = new ArrayList();
        // 倒序遍历数组获取出现顺序从大到小的排列
        for(int i = list.length - 1;i >= 0 && res.size() < k;i--){
            if(list[i] == null) continue;
            res.addAll(list[i]);
        }
        int[] out = new int[res.size()];
        for(int a = 0; a < res.size(); a++){
            out[a] = res.get(a);
        }
        return out;
    }
}

复杂度分析

时间复杂度 O(n) 空间复杂度 O(n)

xinhaoyi commented 2 years ago

347. 前 K 个高频元素

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

思路一

先遍历一遍,用一个哈希表把次数都存起来

然后拿出哈希表中全部的键值对,放进一个优先队列中,优先队列按照value值的大小去排列

最后看k是多少,出队几个就可以了

代码

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        int[] res = new int[k];
        //先遍历一遍,用一个哈希表把次数都存起来
        //然后拿出哈希表中全部的键值对,放进一个优先队列中,优先队列按照value值的大小去排列
        //最后看k是多少,出队几个就可以了
        Map<Integer,Integer> map = new HashMap<>();
        for(int num : nums){
            map.put(num, map.getOrDefault(num, 0) + 1);
        }
        //创建优先队列
        PriorityQueue<Map.Entry<Integer,Integer>> prQueue = 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().compareTo(o1.getValue());
                }
        });
        for(Map.Entry<Integer,Integer> entry : map.entrySet()){
            prQueue.add(entry);
        }
        for(int i = 0; i < k; i++){
            int num = prQueue.poll().getKey();
            res[i] = num;
        }
        return res;
    }
}

复杂度分析

时间复杂度:$O(n)$

空间复杂度:

ggohem commented 2 years ago

思路:

哈希表+堆排序

代码:

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> occurrences = new HashMap<Integer, Integer>();
        for (int num : nums) {
            occurrences.put(num, occurrences.getOrDefault(num, 0) + 1);
        }

        // int[] 的第一个元素代表数组的值,第二个元素代表了该值出现的次数
        PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {
            public int compare(int[] m, int[] n) {
                return m[1] - n[1];
            }
        });
        for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {
            int num = entry.getKey(), count = entry.getValue();
            if (queue.size() == k) {
                if (queue.peek()[1] < count) {
                    queue.poll();
                    queue.offer(new int[]{num, count});
                }
            } else {
                queue.offer(new int[]{num, count});
            }
        }
        int[] ret = new int[k];
        for (int i = 0; i < k; ++i) {
            ret[i] = queue.poll()[0];
        }
        return ret;
    }
}

时空复杂度:

linyang4 commented 2 years ago

思路

  1. 遍历数组, 用map存储数字以及他们出现的数字
  2. 对map进行排序(根据出现次数从大到小), 取出现次数最大的前k个数字

代码

var topKFrequent = function(nums, k) {
    const numMap = new Map()
    for(num of nums) {
        numMap.set(num, (numMap.get(num) || 0) + 1)
    }
    if (numMap.size < k) {
        return [...numMap.keys()]
    }
    return Array.from(numMap.keys())
        .sort((left, right) => numMap.get(right) - numMap.get(left))
        .slice(0, k)
};

复杂度

callmeerika commented 2 years ago

思路

利用map记录出现过的数字和次数,然后返回次数最大的前k个

代码

var topKFrequent = function(nums, k) {
    let hash = new Map();
    for(let i = 0; i < nums.length; i++) {
        if(hash.has(nums[i])){
            let num = hash.get(nums[i]);
            hash.set(nums[i], num + 1);
        } else {
            hash.set(nums[i], 1);
        }
    }
    return [...hash].sort((a,b)=>a[1]-b[1]).slice(-k).map(vv=>vv[0])
};

复杂度

时间复杂度:O(nlogn)
空间复杂度:O(n)

Moin-Jer commented 2 years ago

思路


代码


class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> occurrences = new HashMap<Integer, Integer>();
        for (int num : nums) {
            occurrences.put(num, occurrences.getOrDefault(num, 0) + 1);
        }

        PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {
            public int compare(int[] m, int[] n) {
                return m[1] - n[1];
            }
        });
        for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {
            int num = entry.getKey(), count = entry.getValue();
            if (queue.size() == k) {
                if (queue.peek()[1] < count) {
                    queue.poll();
                    queue.offer(new int[]{num, count});
                }
            } else {
                queue.offer(new int[]{num, count});
            }
        }
        int[] ret = new int[k];
        for (int i = 0; i < k; ++i) {
            ret[i] = queue.poll()[0];
        }
        return ret;
    }
}

复杂度分析


Aobasyp commented 2 years ago

思路 桶的 key 是值,value 是值等于 key 的列表。 初始化一个桶 bucket,一个哈希表 counter 记录数值频次 从最后一个桶开始遍历直到取出 K 个数

class Solution {

public int[] topKFrequent(int[] nums, int k) {

    List<Integer> res = new LinkedList<>();
    List<Integer>[] bucket = new List[nums.length + 1];
    Map<Integer, Integer> counter = new HashMap<>();

    for (int num: nums)
        counter.put(num, counter.getOrDefault(num, 0) + 1);

    for (Map.Entry<Integer, Integer> entry: counter.entrySet()) {
        int val = entry.getValue();
        if (bucket[val] == null)
            bucket[val] = new LinkedList<>();
        bucket[val].add(entry.getKey());
    }

    int kNum = 0;
    for (int i = bucket.length - 1; i >= 0; i--)
        if (bucket[i] != null)
            for (int elem: bucket[i]){

                res.add(elem);
                kNum++;
            }

    int[] ret = new int[k];
    for (int i = 0; i < ret.length; i++)
        ret[i] = res.get(i);

    return ret;
}

}

时间复杂度: O(N) 空间复杂度: O(N)

alongchong commented 2 years ago

代码

class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if (p == null && q == null) {
            return true;
        } else if (p == null || q == null) {
            return false;
        } else if (p.val != q.val) {
            return false;
        } else {
            return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
        }
    }
}
RMadridXDH commented 2 years ago

代码

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        count = collections.Counter(nums)
        return [item[0] for item in count.most_common(k)]
baddate commented 2 years ago

题目

https://leetcode-cn.com/problems/top-k-frequent-elements/

思路

小顶堆,遍历出现次数数组

代码

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        vector<int> ret;
        unordered_map<int, int> mp;
        priority_queue<pair<int, int>> pq;
        for (auto i : nums) mp[i]++;
        for (auto p : mp) {
            pq.push(pair<int, int>(-p.second, p.first));
            if (pq.size() > k) pq.pop();
        }
        while (k--) {
            ret.push_back(pq.top().second);
            pq.pop();
        }
        reverse(ret.begin(),ret.end());
        return ret;
    }
};

复杂度分析

LiFuQuan1208 commented 2 years ago

思路:

循环获取所有值出现的次数,然后转换key 和value的顺序取最大的K个拿出来

代码:

   public int[] topKFrequent(int[] nums, int k) {
        HashMap<Integer, Integer> integerIntegerHashMap = new HashMap<>();
        LinkedList<Integer> integers = new LinkedList<>();
        List<Integer>[] buckets=new List[nums.length+1];
        for (int num:nums) {
            integerIntegerHashMap.put(num,integerIntegerHashMap.getOrDefault(num,0)+1);
        }
        for (Map.Entry<Integer,Integer> entry:integerIntegerHashMap.entrySet()) {
          if(buckets[entry.getValue()]==null){
             buckets[entry.getValue()]=new LinkedList<Integer>();
          }
          buckets[entry.getValue()].add(entry.getKey());
        }
        for(int i=buckets.length-1;i>=0;i++){
            if(buckets[i]!=null){
                for(int element:buckets[i]){
                    integers.add(element);
                }
            }
        }
       int []res= new int[k];
        for(int i=0;i<res.length;i++){
            res[i]=integers.get(i);
        }
        return  res;
moirobinzhang commented 2 years ago

Code:

public class Solution { public int[] TopKFrequent(int[] nums, int k) { Dictionary<int, int> dicNums = new Dictionary<int, int>(); for (int i = 0; i < nums.Length; i++) { if (dicNums.ContainsKey(nums[i])) { dicNums[nums[i]]++; } else { dicNums.Add(nums[i], 1); } }

        List<int>[] bucket = new List<int>[nums.Length + 1];
        foreach (var item in dicNums)
        {
            if (bucket[item.Value] == null)
            {
                bucket[item.Value] = new List<int>();
            }
            bucket[item.Value].Add(item.Key);
        }

        int count = 0;
        int[] result = new int[k];
        for (int i = bucket.Length - 1; i >= 0 ; i--)
        {
            if (bucket[i] == null || bucket[i].Count == 0)
                continue;

            foreach(int item in bucket[i])
            {
                result[count++] = item;
                if(count == k)
                    return result;
            }

        }

        return result;

}

}

Hacker90 commented 2 years ago

思路


class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        // pair<count, val>
        // top k, min heap(小根堆)
        using E = std::pair<int, int>;
        std::priority_queue<E, std::vector<E>, std::greater<E>> minHeap;
        map<int, int> counter;

        for (auto e : nums) {
            ++counter[e];
        }

        for (auto& x : counter) {
            auto pair = make_pair(x.second, x.first);
            if (minHeap.size() == k) {
                if (pair < minHeap.top()) continue;
                minHeap.pop();
            }
            minHeap.push(std::move(pair));
        }
        std::vector<int> res(minHeap.size());
        k = res.size();
        while(!minHeap.empty()) {
            res[--k] = minHeap.top().second;
            minHeap.pop();
        }
        return res;
    }
};

复杂度分析

zwx0641 commented 2 years ago

class Solution { public int[] topKFrequent(int[] nums, int k) { Map<Integer, Integer> map = new HashMap<>(); for (int num : nums) { map.put(num, map.getOrDefault(num, 0) + 1); }

    PriorityQueue<int[]> pq = new PriorityQueue<>(
        (int[] a, int[] b) -> a[1] - b[1]
    );

    for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
        int num = entry.getKey(), count = entry.getValue();
        if (pq.size() == k) {
            if (pq.peek()[1] < count) {
                pq.poll();
                pq.offer(new int[]{num, count});
            }
        } else {
            pq.offer(new int[]{num, count});
        }
    }

    int[] ans = new int[k];
    for (int i = 0; i < k; i++) {
        ans[i] = pq.poll()[0];
    }
    return ans;
}

}

dahaiyidi commented 2 years ago

Problem

347. 前 K 个高频元素

++

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

进阶:你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。


Note


Complexity


Python

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        counts = {}
        max_count = 0
        for n in nums:
            counts[n] = counts.get(n, 0) + 1
            max_count = max(max_count, counts[n])
        buckets = [[] for _ in range(max_count)] # List[List[]] 内部有max_count个[]

        for n, num in counts.items():
            buckets[num - 1].append(n)   # 可能有多个数字是一样的频率

        res = []
        for i in range(len(buckets)-1, -1, -1):
            res.extend(buckets[i])
            if len(res) >= k:
                break
        return res[:k] 

C++

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> counts;
        int max_count = 0;
        for(int num: nums){
            max_count = max(max_count, ++counts[num]);
        }
        vector<vector<int>> buckets(max_count);
        for(pair<int, int> p: counts){
            buckets[p.second - 1].emplace_back(p.first);
        }
        vector<int> res;
        for(int i = max_count - 1; i >= 0; i--){
            for(int n: buckets[i]){
                res.emplace_back(n);
                if(res.size() == k){
                    return res;
                }
            }
        }
        return res;
    }
};

From : https://github.com/dahaiyidi/awsome-leetcode

Zhang6260 commented 2 years ago

JAVA版本

需要考虑数组中的重复的数组

class Solution {
   public int[] topKFrequent(int[] num, int k) {
       HashMap<Integer,Integer> map = new HashMap<>();
       ArrayList<Integer> list = new ArrayList<>();
       for(int i: num){
           map.put(i,map.getOrDefault(i,0)+1);
           if(!list.contains(i))list.add(i);
       }
       int arr[] = new int[list.size()];
       int j=0;
       for(int i:list)arr[j++]=i;
       fun(map,arr,0,arr.length-1);
       //对list进行排序,注意排序的规则是根据 map所对应的value的值。
       //又因为时间复杂度限制为nlogn  只能选择快排或者归并
       int arr_s[]=new int[k];

       for(int i=0;i<k;i++){
           arr_s[i] = arr[i];
       }
       return arr_s;

   }
     //按照从降序排序
   public  void fun(HashMap<Integer,Integer> map,int[]arr,int start,int end){
       if(start>end)return;
       int temp_value=map.get(arr[start]);
       int temp=arr[start];
       int l=start,r=end;
       while (l<r){
           while (l<r&&map.get(arr[r])<=temp_value)r--;
           arr[l]=arr[r];
           while (l<r&&map.get(arr[l])>=temp_value)l++;
           arr[r] = arr[l];
       }
       arr[l]=temp;
       fun(map,arr,start,l-1);
       fun(map,arr,l+1,end);

   }
}

时间复杂度:O(nlogn)

空间复杂度:O(n)

guoling0019 commented 2 years ago

代码

C++ Code:


class Solution {
public:
    class mycomparison {
        public:
            bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
                return lhs.second > rhs.second;
            }
    };
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> map;
        for (int i = 0; i < nums.size(); i++) {
            map[nums[i]]++;
        }

        priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> pri_que;

        for (unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++) {
            pri_que.push(*it);
            if (pri_que.size() > k) {
                pri_que.pop();
            }
        }

        vector<int> ans(k);
        for (int i = k - 1; i >= 0; i--) {
            ans[i] = pri_que.top().first;
            pri_que.pop();
        }
        return ans;
    }
};

复杂度分析

令 n 为数组长度。

last-Battle commented 2 years ago

代码

C++ Code:


class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> m;
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
        vector<int> res;
        for (auto a : nums) {
            ++m[a];
        }

        for (auto& [key, val] : m) {
            q.push(pair<int, int>(val, key));
            if (q.size() > k) {
                q.pop();
            }
        }

        while (!q.empty()) {
            res.emplace_back(q.top().second);
            q.pop();
        }
        return res;
    }
};

复杂度分析

kbfx1234 commented 2 years ago

347. 前 K 个高频元素

//12-31 Happy new year!
class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        map<int,int> mp;
        int len = nums.size();
        vector<int> ans(k,0);
        for (int i = 0; i < len; i++) {
            mp[nums[i]]++;
        }
        vector<pair<int, int>> tmp;
        for (auto &p : mp) {
            tmp.push_back({p.second, p.first});
        }
        sort(tmp.rbegin(),tmp.rend());
        for (int i = 0; i < k; i++) {
            ans[i] = tmp[i].second;
        }
        return ans;
    }
};