diff --git a/solution/0600-0699/0692.Top K Frequent Words/README.md b/solution/0600-0699/0692.Top K Frequent Words/README.md index f586bd7380028..42a2aa142b80c 100644 --- a/solution/0600-0699/0692.Top K Frequent Words/README.md +++ b/solution/0600-0699/0692.Top K Frequent Words/README.md @@ -69,6 +69,12 @@ tags: ### 方法一:哈希表 + 排序 +我们可以用一个哈希表 $\textit{cnt}$ 记录每一个单词出现的次数,然后对哈希表中的键值对按照值进行排序,如果值相同,按照键进行排序。 + +最后取出前 $k$ 个键即可。 + +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为单词的个数。 + #### Python3 @@ -86,23 +92,19 @@ class Solution: class Solution { public List topKFrequent(String[] words, int k) { Map cnt = new HashMap<>(); - for (String v : words) { - cnt.put(v, cnt.getOrDefault(v, 0) + 1); + for (String w : words) { + cnt.merge(w, 1, Integer::sum); } - PriorityQueue q = new PriorityQueue<>((a, b) -> { - int d = cnt.get(a) - cnt.get(b); - return d == 0 ? b.compareTo(a) : d; + Arrays.sort(words, (a, b) -> { + int c1 = cnt.get(a), c2 = cnt.get(b); + return c1 == c2 ? a.compareTo(b) : c2 - c1; }); - for (String v : cnt.keySet()) { - q.offer(v); - if (q.size() > k) { - q.poll(); + List ans = new ArrayList<>(); + for (int i = 0; i < words.length && ans.size() < k; ++i) { + if (i == 0 || !words[i].equals(words[i - 1])) { + ans.add(words[i]); } } - LinkedList ans = new LinkedList<>(); - while (!q.isEmpty()) { - ans.addFirst(q.poll()); - } return ans; } } @@ -115,13 +117,17 @@ class Solution { public: vector topKFrequent(vector& words, int k) { unordered_map cnt; - for (auto& v : words) ++cnt[v]; + for (const auto& w : words) { + ++cnt[w]; + } vector ans; - for (auto& [key, _] : cnt) ans.emplace_back(key); - sort(ans.begin(), ans.end(), [&](const string& a, const string& b) -> bool { - return cnt[a] == cnt[b] ? a < b : cnt[a] > cnt[b]; + for (const auto& [w, _] : cnt) { + ans.push_back(w); + } + ranges::sort(ans, [&](const string& a, const string& b) { + return cnt[a] > cnt[b] || (cnt[a] == cnt[b] && a < b); }); - ans.erase(ans.begin() + k, ans.end()); + ans.resize(k); return ans; } }; @@ -130,23 +136,35 @@ public: #### Go ```go -func topKFrequent(words []string, k int) []string { +func topKFrequent(words []string, k int) (ans []string) { cnt := map[string]int{} - for _, v := range words { - cnt[v]++ + for _, w := range words { + cnt[w]++ } - ans := []string{} - for v := range cnt { - ans = append(ans, v) + for w := range cnt { + ans = append(ans, w) } - sort.Slice(ans, func(i, j int) bool { - a, b := ans[i], ans[j] - return cnt[a] > cnt[b] || cnt[a] == cnt[b] && a < b - }) + sort.Slice(ans, func(i, j int) bool { a, b := ans[i], ans[j]; return cnt[a] > cnt[b] || cnt[a] == cnt[b] && a < b }) return ans[:k] } ``` +#### TypeScript + +```ts +function topKFrequent(words: string[], k: number): string[] { + const cnt: Map = new Map(); + for (const w of words) { + cnt.set(w, (cnt.get(w) || 0) + 1); + } + const ans: string[] = Array.from(cnt.keys()); + ans.sort((a, b) => { + return cnt.get(a) === cnt.get(b) ? a.localeCompare(b) : cnt.get(b)! - cnt.get(a)!; + }); + return ans.slice(0, k); +} +``` + diff --git a/solution/0600-0699/0692.Top K Frequent Words/README_EN.md b/solution/0600-0699/0692.Top K Frequent Words/README_EN.md index 8a85971974a4e..3aaadb00169d2 100644 --- a/solution/0600-0699/0692.Top K Frequent Words/README_EN.md +++ b/solution/0600-0699/0692.Top K Frequent Words/README_EN.md @@ -63,7 +63,13 @@ Note that "i" comes before "love" due to a lower alphabetica -### Solution 1 +### Solution 1: Hash Table + Sorting + +We can use a hash table $\textit{cnt}$ to record the frequency of each word. Then, we sort the key-value pairs in the hash table by value, and if the values are the same, we sort by key. + +Finally, we take the first $k$ keys. + +The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Here, $n$ is the number of words. @@ -82,23 +88,19 @@ class Solution: class Solution { public List topKFrequent(String[] words, int k) { Map cnt = new HashMap<>(); - for (String v : words) { - cnt.put(v, cnt.getOrDefault(v, 0) + 1); + for (String w : words) { + cnt.merge(w, 1, Integer::sum); } - PriorityQueue q = new PriorityQueue<>((a, b) -> { - int d = cnt.get(a) - cnt.get(b); - return d == 0 ? b.compareTo(a) : d; + Arrays.sort(words, (a, b) -> { + int c1 = cnt.get(a), c2 = cnt.get(b); + return c1 == c2 ? a.compareTo(b) : c2 - c1; }); - for (String v : cnt.keySet()) { - q.offer(v); - if (q.size() > k) { - q.poll(); + List ans = new ArrayList<>(); + for (int i = 0; i < words.length && ans.size() < k; ++i) { + if (i == 0 || !words[i].equals(words[i - 1])) { + ans.add(words[i]); } } - LinkedList ans = new LinkedList<>(); - while (!q.isEmpty()) { - ans.addFirst(q.poll()); - } return ans; } } @@ -111,13 +113,17 @@ class Solution { public: vector topKFrequent(vector& words, int k) { unordered_map cnt; - for (auto& v : words) ++cnt[v]; + for (const auto& w : words) { + ++cnt[w]; + } vector ans; - for (auto& [key, _] : cnt) ans.emplace_back(key); - sort(ans.begin(), ans.end(), [&](const string& a, const string& b) -> bool { - return cnt[a] == cnt[b] ? a < b : cnt[a] > cnt[b]; + for (const auto& [w, _] : cnt) { + ans.push_back(w); + } + ranges::sort(ans, [&](const string& a, const string& b) { + return cnt[a] > cnt[b] || (cnt[a] == cnt[b] && a < b); }); - ans.erase(ans.begin() + k, ans.end()); + ans.resize(k); return ans; } }; @@ -126,23 +132,35 @@ public: #### Go ```go -func topKFrequent(words []string, k int) []string { +func topKFrequent(words []string, k int) (ans []string) { cnt := map[string]int{} - for _, v := range words { - cnt[v]++ + for _, w := range words { + cnt[w]++ } - ans := []string{} - for v := range cnt { - ans = append(ans, v) + for w := range cnt { + ans = append(ans, w) } - sort.Slice(ans, func(i, j int) bool { - a, b := ans[i], ans[j] - return cnt[a] > cnt[b] || cnt[a] == cnt[b] && a < b - }) + sort.Slice(ans, func(i, j int) bool { a, b := ans[i], ans[j]; return cnt[a] > cnt[b] || cnt[a] == cnt[b] && a < b }) return ans[:k] } ``` +#### TypeScript + +```ts +function topKFrequent(words: string[], k: number): string[] { + const cnt: Map = new Map(); + for (const w of words) { + cnt.set(w, (cnt.get(w) || 0) + 1); + } + const ans: string[] = Array.from(cnt.keys()); + ans.sort((a, b) => { + return cnt.get(a) === cnt.get(b) ? a.localeCompare(b) : cnt.get(b)! - cnt.get(a)!; + }); + return ans.slice(0, k); +} +``` + diff --git a/solution/0600-0699/0692.Top K Frequent Words/Solution.cpp b/solution/0600-0699/0692.Top K Frequent Words/Solution.cpp index 0cf538a10bcd6..d3310d794a8bf 100644 --- a/solution/0600-0699/0692.Top K Frequent Words/Solution.cpp +++ b/solution/0600-0699/0692.Top K Frequent Words/Solution.cpp @@ -2,13 +2,17 @@ class Solution { public: vector topKFrequent(vector& words, int k) { unordered_map cnt; - for (auto& v : words) ++cnt[v]; + for (const auto& w : words) { + ++cnt[w]; + } vector ans; - for (auto& [key, _] : cnt) ans.emplace_back(key); - sort(ans.begin(), ans.end(), [&](const string& a, const string& b) -> bool { - return cnt[a] == cnt[b] ? a < b : cnt[a] > cnt[b]; + for (const auto& [w, _] : cnt) { + ans.push_back(w); + } + ranges::sort(ans, [&](const string& a, const string& b) { + return cnt[a] > cnt[b] || (cnt[a] == cnt[b] && a < b); }); - ans.erase(ans.begin() + k, ans.end()); + ans.resize(k); return ans; } -}; \ No newline at end of file +}; diff --git a/solution/0600-0699/0692.Top K Frequent Words/Solution.go b/solution/0600-0699/0692.Top K Frequent Words/Solution.go index 948808c9d10e2..5ddb3abcbc921 100644 --- a/solution/0600-0699/0692.Top K Frequent Words/Solution.go +++ b/solution/0600-0699/0692.Top K Frequent Words/Solution.go @@ -1,15 +1,11 @@ -func topKFrequent(words []string, k int) []string { +func topKFrequent(words []string, k int) (ans []string) { cnt := map[string]int{} - for _, v := range words { - cnt[v]++ + for _, w := range words { + cnt[w]++ } - ans := []string{} - for v := range cnt { - ans = append(ans, v) + for w := range cnt { + ans = append(ans, w) } - sort.Slice(ans, func(i, j int) bool { - a, b := ans[i], ans[j] - return cnt[a] > cnt[b] || cnt[a] == cnt[b] && a < b - }) + sort.Slice(ans, func(i, j int) bool { a, b := ans[i], ans[j]; return cnt[a] > cnt[b] || cnt[a] == cnt[b] && a < b }) return ans[:k] -} \ No newline at end of file +} diff --git a/solution/0600-0699/0692.Top K Frequent Words/Solution.java b/solution/0600-0699/0692.Top K Frequent Words/Solution.java index 16e47ddaccf72..0af0bec06f628 100644 --- a/solution/0600-0699/0692.Top K Frequent Words/Solution.java +++ b/solution/0600-0699/0692.Top K Frequent Words/Solution.java @@ -1,23 +1,19 @@ class Solution { public List topKFrequent(String[] words, int k) { Map cnt = new HashMap<>(); - for (String v : words) { - cnt.put(v, cnt.getOrDefault(v, 0) + 1); + for (String w : words) { + cnt.merge(w, 1, Integer::sum); } - PriorityQueue q = new PriorityQueue<>((a, b) -> { - int d = cnt.get(a) - cnt.get(b); - return d == 0 ? b.compareTo(a) : d; + Arrays.sort(words, (a, b) -> { + int c1 = cnt.get(a), c2 = cnt.get(b); + return c1 == c2 ? a.compareTo(b) : c2 - c1; }); - for (String v : cnt.keySet()) { - q.offer(v); - if (q.size() > k) { - q.poll(); + List ans = new ArrayList<>(); + for (int i = 0; i < words.length && ans.size() < k; ++i) { + if (i == 0 || !words[i].equals(words[i - 1])) { + ans.add(words[i]); } } - LinkedList ans = new LinkedList<>(); - while (!q.isEmpty()) { - ans.addFirst(q.poll()); - } return ans; } -} \ No newline at end of file +} diff --git a/solution/0600-0699/0692.Top K Frequent Words/Solution.ts b/solution/0600-0699/0692.Top K Frequent Words/Solution.ts new file mode 100644 index 0000000000000..ff1439615430e --- /dev/null +++ b/solution/0600-0699/0692.Top K Frequent Words/Solution.ts @@ -0,0 +1,11 @@ +function topKFrequent(words: string[], k: number): string[] { + const cnt: Map = new Map(); + for (const w of words) { + cnt.set(w, (cnt.get(w) || 0) + 1); + } + const ans: string[] = Array.from(cnt.keys()); + ans.sort((a, b) => { + return cnt.get(a) === cnt.get(b) ? a.localeCompare(b) : cnt.get(b)! - cnt.get(a)!; + }); + return ans.slice(0, k); +}