[Medium] 692. Top K Frequent Words
Given an array of strings words and an integer k, return the k most frequent strings.
Return the answer sorted by the frequency from highest to lowest. Sort the words with the same frequency by their lexicographical order.
Examples
Example 1:
Input: words = ["i","love","leetcode","i","love","coding"], k = 2
Output: ["i","love"]
Explanation: "i" and "love" are the two most frequent words.
Note that "i" comes before "love" due to a lower alphabetical order.
Example 2:
Input: words = ["the","day","is","sunny","the","the","the","sunny","is","is"], k = 2
Output: ["the","is"]
Explanation: "the", "is", "sunny" and "day" are the four most frequent words, with the number of occurrence being 4, 3, 2 and 1 respectively.
Constraints
1 <= words.length <= 5001 <= words[i].length <= 10words[i]consists of lowercase English letters.kis in the range[1, The number of unique words[i]]
Thinking Process
- Custom Comparator: The key is the two-level sorting: frequency first, then lexicographic order
- Heap gives fast access to min/max without full sorting.
- Size-k heap handles Top-K in O(n log k).
- Lazy deletion when elements leave the heap before removal.
Common Approaches
Typical techniques for this pattern:
| Approach | Time | Space | Notes |
|---|---|---|---|
| Min/max heap (this problem) | O(n log k) | O(k) | Top-K, streaming median |
| Two heaps | O(n log n) | O(n) | Median from data stream |
| Heap + lazy deletion | O(n log n) | O(n) | Delayed removal |
| Priority-driven search | O(n log n) | O(n) | Dijkstra, best-first expansion |
Solution
Solution: Hash Map + Custom Sorting
class Solution:
def topKFrequent(self, words, k):
cnt = {}
for word in words:
cnt[word] = cnt.get(word, 0) + 1
rtn = list(cnt.keys())
rtn.sort(key=lambda a: (-cnt[a], a))
return rtn[:k]
Solution Explanation
Approach: Min/max heap (this problem)
Key idea: 1. Custom Comparator: The key is the two-level sorting: frequency first, then lexicographic order
How the code works:
- Custom Comparator: The key is the two-level sorting: frequency first, then lexicographic order
- Heap gives fast access to min/max without full sorting.
- Size-k heap handles Top-K in O(n log k).
- Lazy deletion when elements leave the heap before removal.
Walkthrough — input words = ["i","love","leetcode","i","love","coding"], k = 2, expected output ["i","love"]:
“i” and “love” are the two most frequent words. Note that “i” comes before “love” due to a lower alphabetical order.
Related Problems
- LC 347: Top K Frequent Elements - Similar problem with integers
- LC 215: Kth Largest Element in an Array - Kth largest element
- LC 451: Sort Characters By Frequency - Sort by frequency
- LC 973: K Closest Points to Origin - Top K with custom ordering
Common Mistakes
- Skipping edge cases (empty input, single element, boundaries).
- Off-by-one errors in loops and index ranges.
- Forgetting to handle the case when no valid answer exists.
Key Takeaways
- Custom Comparator: The key is the two-level sorting: frequency first, then lexicographic order
- Hash Map Efficiency:
unordered_mapprovides O(1) average case for frequency counting - Sorting Trade-off: Simple sorting works well for small inputs; heap is better for large k
- Lexicographic Order: When frequencies are equal, use standard string comparison (
<)
References
- LC 692: Top K Frequent Words on LeetCode
- LeetCode Discuss — LC 692: Top K Frequent Words
- LeetCode Editorial (may require premium)