LeetCode 290 单词规律

1. 题目

290. 单词规律 - 力扣(LeetCode)

题目描述

给定一种规律 pattern 和一个字符串 s ,判断字符串是否遵循相同的规律。

这里的遵循指完全匹配,例如,pattern 里的每个字母和字符串 s 中的每个非空单词之间存在双向一一映射的对应关系。

示例

输入:pattern = "abba", s = "dog cat cat dog"

输出:true

输入:pattern = "abba", s = "dog cat cat fish"

输出:false

输入:pattern = "aaaa", s = "dog cat cat dog"

输出:false

输入:pattern = "abba", s = "dog dog dog dog"

输出:false

约束

  • 1≤pattern.length≤300

  • 1≤s.length≤3000

  • s 只包含小写英文字母和单个空格,单词之间由单个空格分隔

  • pattern 只包含小写英文字母

2. 最佳解题思路描述(双向哈希映射 + stringstream 分割单词)

  1. 使用 stringstream 按空格分割字符串 s,提取所有单词存入数组;

  2. 提前校验长度:pattern 字符数量必须等于单词总数,不等直接返回 false;

  3. 建立两张哈希表实现双向唯一映射:

    • charToStr:pattern 字符 → 单词

    • strToChar:单词 → pattern 字符

  4. 同步遍历每个下标:

    • 若字符已有映射,映射单词必须和当前单词一致,否则不匹配;

    • 若字符无映射但当前单词已有反向映射,说明多对一冲突,返回 false;

    • 无任何映射则双向存入哈希表;

  5. 全程无冲突则返回 true。

优势

完全复用 LC205 同构字符串的双向映射模板,逻辑统一,能拦截一对多、多对一两种非法映射;时间 O(n),n 为单词总数。

3. 可优化代码(逻辑完全正确,仅命名、格式优化)

复制代码
#include <sstream>
#include <vector>
#include <unordered_map>
using namespace std;
class Solution {
public:
    bool wordPattern(string s, string t) {
        vector<string> words;
        stringstream ss(t);
        string word;
        while(ss >> word){
            words.push_back(word);
        }
​
        unordered_map<char,string>hash;
        unordered_map<string,char>hash2;
        if (s.size() != words.size())
            return false;
        for(int i = 0;i<s.size();i++){
            
            char c = s[i];
            string c2 = words[i];
            auto it = hash.find(c);
            auto it2 = hash2.find(c2);
            if(it != hash.end()){
                if(it->second != c2) return false;
            }
            else if(it2 != hash2.end()){
                if(it2->second != c) return false;
            }
            else{
                hash[c] = c2;
                hash2[c2] = c;
            }
        }
        return true;
    }
};

代码说明

  1. 正确性:无逻辑 bug,全部测试用例可通过,是标准解法;

  2. 可优化 / 规范点:

    • 变量命名语义模糊:hashchar2wordhash2word2char

    • 参数命名易混淆:形参s存 pattern、t存句子,建议改为patternstr提升可读性;

    • 可提前缓存 pattern.size(),避免循环重复取值;

    • 增加代码空格、换行,分支层次更清晰。

4. 规范优化版代码

复制代码
#include <sstream>
#include <vector>
#include <unordered_map>
using namespace std;
class Solution {
public:
    bool wordPattern(string pattern, string str) {
        vector<string> words;
        stringstream ss(str);
        string word;
        while (ss >> word) {
            words.push_back(word);
        }
        int n = pattern.size();
        if (n != words.size()) return false;
​
        unordered_map<char, string> char2word;
        unordered_map<string, char> word2char;
        for (int i = 0; i < n; ++i) {
            char ch = pattern[i];
            string wd = words[i];
            auto it1 = char2word.find(ch);
            auto it2 = word2char.find(wd);
​
            if (it1 != char2word.end()) {
                if (it1->second != wd) return false;
            } else if (it2 != word2char.end()) {
                if (it2->second != ch) return false;
            } else {
                char2word[ch] = wd;
                word2char[wd] = ch;
            }
        }
        return true;
    }
};

5. 总结

  1. 本题和 LC205 同构字符串是同模板题型,区别仅为映射对象:字符↔单词;

  2. 核心必做两步:分割单词、双向哈希校验,缺一不可;

  3. 关键边界判断:pattern 长度和单词数组长度不一致直接 false;

  4. 只使用单向哈希会出现多对一误判(如 abba + dog dog dog dog),必须两张 map 双向校验。

6. 相关知识拓展

拓展 1:stringstream 分割特性

ss >> word 会自动以任意空白符分割,忽略首尾空格,完美适配本题单词分割需求;

若题目需要保留连续空格、多行文本,该方法不适用。

拓展 2:LC205 与 LC290 对比

题目 映射关系 处理步骤
205 同构字符串 char ↔ char 直接遍历双字符串,无需分割
290 单词规律 char ↔ string 先分割句子为单词数组,再双向映射

拓展 3:易错坑点

  1. 忘记判断 pattern 长度与单词数组长度,如 pattern="abc"、句子只有 2 个单词;

  2. 仅使用一张单向哈希表,无法拦截多个字符映射同一个单词;

  3. 参数命名混淆 pattern 和句子,循环取值下标错位。

拓展 4:复杂度分析

  • 时间复杂度 O(N):N 为句子总字符数,分割 + 遍历各一次;

  • 空间复杂度 O(M):M 为不重复单词数量,哈希表存储映射关系。

相关推荐
liliangcsdn1 小时前
多空价差收益序列汇总统计的分析和代码示例
人工智能·算法·机器学习
啥都想学点的研究生1 小时前
一篇文章讲清楚:Adaboost算法与GBDT
人工智能·算法
旖旎夜光1 小时前
LeetCode 525:连续数组(前缀和) —— 题解
数据结构·c++·算法·leetcode·前缀和
zander2582 小时前
LeetCode 32. 最长有效括号
算法
lvwangshu2 小时前
AC 自动机
算法·字符串
shehuiyuelaiyuehao11 小时前
算法31,前缀和,可被k整除的子数组
数据结构·python·算法
203号居民13 小时前
LeetCode hot 100 — 141. 环形链表2
算法·leetcode·链表
玖玥拾13 小时前
LeetCode 202 快乐数
算法·leetcode
LuminousCPP13 小时前
数据结构-二叉树(六):BFS层序遍历与完全二叉树判断|复用链式队列 + (N_0=N_2+1) 性质证明
c语言·数据结构·笔记·算法·二叉树·宽度优先