在问 · 算法题解

290. 单词规律

题目描述

输入一个由小写字母组成的模式串 pattern,以及一个由单词构成、单词之间用一个空格隔开的字符串 s。

判断 s 是否与 pattern 完全匹配。匹配的意思是:pattern 的第 i 个字母对应 s 的第 i 个单词,并且字母和单词之间是一一对应的关系。同一个字母必须总对应同一个单词,不同字母不能对应同一个单词。字母个数和单词个数不相等时也不匹配。

匹配返回 true,否则返回 false。

示例 1
输入:pattern = "abba", s = "dog cat cat dog"
输出:true

解释:a 对应 dog,b 对应 cat,前后一致。

示例 2
输入:pattern = "abba", s = "dog cat cat fish"
输出:false

解释:a 在第 1 位对应 dog,在第 4 位却对应 fish。

示例 3
输入:pattern = "aaaa", s = "dog cat cat dog"
输出:false

解释:a 同时对应了 dog 和 cat 两个不同的单词。

数据范围

  • 1 <= pattern.length <= 300
  • pattern 只含小写英文字母。
  • 1 <= s.length <= 3000
  • s 只含小写英文字母和空格 " "。
  • s 首尾没有空格。
  • s 中相邻单词之间正好隔一个空格。

解题思路

先把 s 按空格切成单词,数量和 pattern 长度不同直接返回 false。之后和「同构字符串」一样用两张哈希表:pw 记录字母 → 单词,wp 记录单词 → 字母。逐对检查,任一方向已有的记录与当前配对不一致就返回 false。

为什么正确

处理完前 i 对后,pw 与 wp 互为逆映射,且前 i 个字母经 pw 映射恰好得到前 i 个单词。

复杂度分析

时间 O(n + m),n 为 pattern 长度,m 为 s 长度;空间 O(m)。

易错点

只建一张字母 → 单词的表会把 pattern="abba", s="dog dog dog dog" 误判为 true;忘记比较单词数量,则 zip 会悄悄截断多余的部分。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def wordPattern(self, pattern: str, s: str) -> bool:
        words = s.split()
        if len(words) != len(pattern):
            return False
        pw, wp = {}, {}
        for c, w in zip(pattern, words):
            if pw.get(c, w) != w or wp.get(w, c) != c:
                return False
            pw[c] = w
            wp[w] = c
        return True

载入编辑器,自己跑一遍 →

字符串 专题的其他题目

查看 字符串 全部题目 →