
核心解题思路:双哈希表双向校验
两个哈希表的分工
-
ch2word(字符→单词)- key:pattern 里的单个字母
- value:该字母对应的单词
- 作用:校验「一个字母只能对应一个单词」
-
word2ch(单词→字符)- key:s 里的单个单词
- value:该单词对应的字母
- 作用:校验「一个单词只能对应一个字母」
核心逻辑
遍历每一组「字母 + 对应单词」,每一步做两次冲突检查:
- 如果这个字母已经存过映射,但对应的单词不是当前单词 → 冲突,返回 false
- 如果这个单词已经存过映射,但对应的字母不是当前字母 → 冲突,返回 false 两次检查都通过,就把这组对应关系存入两个哈希表,继续下一组。
完整解题步骤
步骤 1:拆分单词(C++ 必手写)
C++ 没有内置的字符串分割函数,需要手动把 s 按空格切割成单词数组。
- 遍历字符串 s,遇到空格就截断,把每个单词存入
vector<string> words - 快速预判 :如果
words.size() != pattern.size(),数量都对不上,直接返回 false
步骤 2:初始化两个哈希表
unordered_map<char, string> ch2word; // 字母 → 单词
unordered_map<string, char> word2ch; // 单词 → 字母
步骤 3:逐位遍历,双向校验
遍历下标 i 从 0 到 pattern末尾:
取出当前字母 c = pattern[i]
取出当前单词 w = words[i]
检查1:c 已经在 ch2word 里,但 ch2word[c] != w → 冲突,返回 false
检查2:w 已经在 word2ch 里,但 word2ch[w] != c → 冲突,返回 false
都没问题:更新两个哈希表,存入 c ↔ w 的映射
步骤 4:遍历完成,无冲突 → 返回 true
cpp
class Solution {
public:
bool wordPattern(string pattern, string s) {
//数组用来存拆分好的单词
vector<string> words;
//拆分
int n = s.size();
int i = 0;
while(i<n){
while(i<n&&s[i]==' '){
i++;
}
if(i>=n) break;
//找到当前单词的结尾
int j = i;
while(j<n && s[j]!=' '){
j++;
}
words.push_back(s.substr(i,j-i));
i = j;
}
if(pattern.size()!= words.size()){
return false;
}
unordered_map<char,string> ch2word;
unordered_map<string,char> word2ch;
for(int k = 0;k<pattern.size();k++){
char c = pattern[k];
string w = words[k];
if(ch2word.count(c)&&ch2word[c]!=w){
return false;
}
if(word2ch.count(w)&&word2ch[w]!=c){
return false;
}
//更新双向映射
ch2word[c] = w;
word2ch[w] = c;
}
return true;
}
};