Top K Frequent Elements 好久没刷题了,做了道之前做过的 medium 难度的题 Top K Frequent Elements
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.
思路 分成两步来解决:
先用 Map 统计下每个数出现的次数, 剩下的就是一个 TopN 问题;
遍历 Map 中的键值对, 遍历过程中维护一个容量为K的小顶堆.
小顶堆维护过程如下:
如果小顶堆中元素不足K个, 将当前元素添加到堆中;
如果小顶堆中有K个元素, 并且当前 key 的出现次数大于堆顶的 key 的出现次数, 就用当前 key 替换堆顶 key, 并维护小顶堆性质.
代码 这里用 kotlin
来实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 class Solution { fun topKFrequent (nums: IntArray, k: Int) : List<Int> { val map = HashMap<Int, Int>() nums.forEach { map[it] = (map[it]?:0 ) + 1 } if (k >= map.keys.size) { return map.keys.toList() } val result = ArrayList<Int>(k) map.forEach { (key, value) -> if (result.size < k) { result.add(key) var i = result.lastIndex while (i > 0 ) { val tmp = (i - 1 ) / 2 if (map[result[tmp]]!! <= value) { break } else { result[i] = result[tmp] result[tmp] = key i = tmp } } } else { if (map[result[0 ]]!! >= value) { return @forEach } var i = 0 var minIndex = 0 val maxIndex = result.lastIndex do { result[i] = result[minIndex] result[minIndex] = key i = minIndex var tmp = 2 * i + 1 if (tmp > maxIndex) { break } if (map[result[tmp]]!! < map[result[minIndex]]!!) { minIndex = tmp } tmp += 1 if (tmp <= maxIndex && map[result[tmp]]!! < map[result[minIndex]]!!) { minIndex = tmp } } while (i != minIndex) } } return result } }