LeetCode 2085: Count Common Words With One Occurrence (Hash Map Frequency Intersection)
LeetCode 2085Hash TableCountingToday we solve LeetCode 2085 - Count Common Words With One Occurrence.
Source: https://leetcode.com/problems/count-common-words-with-one-occurrence/
English
Problem Summary
Given two string arrays words1 and words2, return how many words appear exactly once in words1 and also appear exactly once in words2.
Key Insight
The condition depends on exact frequencies, so we first build one frequency map for each array. Then scan one map: if a word has count 1 in both maps, it contributes 1 to the answer.
Algorithm
- Build freq1 from words1.
- Build freq2 from words2.
- Initialize answer = 0.
- For each word in freq1, if freq1[word] == 1 and freq2[word] == 1, increment answer.
- Return answer.
Complexity Analysis
Let n = words1.length, m = words2.length.
Time: O(n + m).
Space: O(n + m) in worst case for distinct words.
Common Pitfalls
- Counting words that appear once in one array but multiple times in the other.
- Using set intersection (presence only) instead of frequency intersection.
- Forgetting that missing key in freq2 should be treated as zero.
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class Solution {
public int countWords(String[] words1, String[] words2) {
Map<String, Integer> freq1 = new HashMap<>();
Map<String, Integer> freq2 = new HashMap<>();
for (String w : words1) {
freq1.put(w, freq1.getOrDefault(w, 0) + 1);
}
for (String w : words2) {
freq2.put(w, freq2.getOrDefault(w, 0) + 1);
}
int answer = 0;
for (Map.Entry<String, Integer> e : freq1.entrySet()) {
String word = e.getKey();
if (e.getValue() == 1 && freq2.getOrDefault(word, 0) == 1) {
answer++;
}
}
return answer;
}
}func countWords(words1 []string, words2 []string) int {
freq1 := map[string]int{}
freq2 := map[string]int{}
for _, w := range words1 {
freq1[w]++
}
for _, w := range words2 {
freq2[w]++
}
ans := 0
for w, c := range freq1 {
if c == 1 && freq2[w] == 1 {
ans++
}
}
return ans
}class Solution {
public:
int countWords(vector<string>& words1, vector<string>& words2) {
unordered_map<string, int> freq1, freq2;
for (const string& w : words1) freq1[w]++;
for (const string& w : words2) freq2[w]++;
int ans = 0;
for (const auto& [word, count] : freq1) {
if (count == 1 && freq2[word] == 1) {
ans++;
}
}
return ans;
}
};from collections import Counter
class Solution:
def countWords(self, words1: List[str], words2: List[str]) -> int:
freq1 = Counter(words1)
freq2 = Counter(words2)
ans = 0
for word, count in freq1.items():
if count == 1 and freq2.get(word, 0) == 1:
ans += 1
return ansvar countWords = function(words1, words2) {
const freq1 = new Map();
const freq2 = new Map();
for (const w of words1) {
freq1.set(w, (freq1.get(w) || 0) + 1);
}
for (const w of words2) {
freq2.set(w, (freq2.get(w) || 0) + 1);
}
let ans = 0;
for (const [word, count] of freq1.entries()) {
if (count === 1 && (freq2.get(word) || 0) === 1) {
ans++;
}
}
return ans;
};中文
题目概述
给定两个字符串数组 words1 和 words2,请返回:有多少个单词在 words1 中恰好出现一次,并且在 words2 中也恰好出现一次。
核心思路
这是“频次精确匹配”问题,不是普通交集。先分别统计两个数组的词频,然后只统计那些在两个词频表里都等于 1 的单词。
算法步骤
- 统计 words1 得到 freq1。
- 统计 words2 得到 freq2。
- 初始化答案 ans = 0。
- 遍历 freq1 中每个单词:若 freq1[word] == 1 且 freq2[word] == 1,则 ans++。
- 返回 ans。
复杂度分析
设 n = words1.length,m = words2.length。
时间复杂度:O(n + m)。
空间复杂度:O(n + m)(最坏情况下单词都不同)。
常见陷阱
- 把“只出现一次”误写成“出现过就算”。
- 只用集合交集,丢失频次信息。
- 读取 freq2 时没处理不存在键(应视为 0)。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
public int countWords(String[] words1, String[] words2) {
Map<String, Integer> freq1 = new HashMap<>();
Map<String, Integer> freq2 = new HashMap<>();
for (String w : words1) {
freq1.put(w, freq1.getOrDefault(w, 0) + 1);
}
for (String w : words2) {
freq2.put(w, freq2.getOrDefault(w, 0) + 1);
}
int answer = 0;
for (Map.Entry<String, Integer> e : freq1.entrySet()) {
String word = e.getKey();
if (e.getValue() == 1 && freq2.getOrDefault(word, 0) == 1) {
answer++;
}
}
return answer;
}
}func countWords(words1 []string, words2 []string) int {
freq1 := map[string]int{}
freq2 := map[string]int{}
for _, w := range words1 {
freq1[w]++
}
for _, w := range words2 {
freq2[w]++
}
ans := 0
for w, c := range freq1 {
if c == 1 && freq2[w] == 1 {
ans++
}
}
return ans
}class Solution {
public:
int countWords(vector<string>& words1, vector<string>& words2) {
unordered_map<string, int> freq1, freq2;
for (const string& w : words1) freq1[w]++;
for (const string& w : words2) freq2[w]++;
int ans = 0;
for (const auto& [word, count] : freq1) {
if (count == 1 && freq2[word] == 1) {
ans++;
}
}
return ans;
}
};from collections import Counter
class Solution:
def countWords(self, words1: List[str], words2: List[str]) -> int:
freq1 = Counter(words1)
freq2 = Counter(words2)
ans = 0
for word, count in freq1.items():
if count == 1 and freq2.get(word, 0) == 1:
ans += 1
return ansvar countWords = function(words1, words2) {
const freq1 = new Map();
const freq2 = new Map();
for (const w of words1) {
freq1.set(w, (freq1.get(w) || 0) + 1);
}
for (const w of words2) {
freq2.set(w, (freq2.get(w) || 0) + 1);
}
let ans = 0;
for (const [word, count] of freq1.entries()) {
if (count === 1 && (freq2.get(word) || 0) === 1) {
ans++;
}
}
return ans;
};
Comments