zoukankan      html  css  js  c++  java
  • 前 K 个高频元素

    题目

    给定一个非空的整数数组,返回其中出现频率前 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 个高频元素的集合是唯一的。你可以按任意顺序返回答案。

    解题思路

    哈希表-优先队列

    这道常考题的经典做法,必须掌握!

    • 先用 哈希表 来建立数字和其出现次数的映射,遍历一遍数组统计元素的频率
    • 维护一个元素数目为 K 的优先队列

    这里要前K个高频元素,也就是按从大到小排序,所以使用最小堆。(同理,若要从小到大排序,则使用最大堆)

    1. 每次都将新的元素与堆顶元素(堆中频率最小的元素)进行比较;
    2. 如果新的元素的频率比堆顶端的元素大,则弹出堆顶端的元素,将新的元素添加进堆中;
    3. 所以最终,堆中的 k 个元素即为前 k 个高频元素。

    代码

    方法1:
    //go
    // go中没有自带的优先队列,需要自己实现小根堆
    func topKFrequent(nums []int, k int) []int {
     if k == 0 || len(nums) == 0 {
      return make([]int, 0)
     }
     // 1. 初始化map
     m := make(map[int]int)
     for _, v := range nums {
      m[v] = m[v] + 1
     }
    
     // 2. 放到小根堆里面
     h := &NodeHeap{}
     topK := min(k, len(m))
     size := 0
     for k, v := range m {
      if size < topK {
       heap.Push(h, &Node{
        val:   k,
        times: v,
       })
       size++
      } else {
       if v > (*h)[0].times {
        heap.Pop(h)
        heap.Push(h, &Node{
         val:   k,
         times: v,
        })
       }
      }
    
     }
    
     // 3.收集答案
     res := make([]int, 0, topK)
     for i := 0; i < topK; i++ {
      res = append(res, heap.Pop(h).(*Node).val)
     }
     return res
    }
    
    type Node struct {
     val   int
     times int
    }
    
    type NodeHeap []*Node
    
    func (h NodeHeap) Len() int { return len(h) }
    
    // 小根堆
    func (h NodeHeap) Less(i, j int) bool { return h[i].times < h[j].times }
    
    func (h NodeHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
    
    func (h *NodeHeap) Push(x interface{}) {
     *h = append(*h, x.(*Node))
    }
    
    func (h *NodeHeap) Pop() interface{} {
     old := *h
     n := len(old)
     x := old[n-1]
     *h = old[0 : n-1]
     return x
    }
    
    func min(a, b int) int {
     if a < b {
      return a
     }
     return b
    }
    方法二:
    func topKFrequency(nums []int, k int) []int{
    	if k <= 0 || len(nums) < k {
    		return make([]int, 0)
    	}
    
    	mapCount := make(map[int]int)
    	var sK []int
    	for _, v := range nums {
    		if _, ok := mapCount[v]; ok {
    			mapCount[v] += 1
    		} else {
    			mapCount[v] = 1
    			sK = append(sK, v)
    		}
    	}
    
    	sort.SliceStable(sK, func(i, j int) bool {
    
    		return mapCount[sK[i]] > mapCount[sK[j]]
    	})
    
    	return sK[:k]
    }
    

      地址:https://mp.weixin.qq.com/s/OuvPhV-UOWYvrtX-O2Xiig

  • 相关阅读:
    表操作
    mysql表的完整性约束
    mysql支持的数据类型
    数据库存储引擎
    Navicat工具、pymysql模块、数据备份
    数据库一
    IO模型
    协成
    线程
    进程
  • 原文地址:https://www.cnblogs.com/smallleiit/p/14042994.html
Copyright © 2011-2022 走看看