LeetCode890. 查找和替换模式


LeetCode890. 查找和替换模式

题目描述

本题目来自LeetCode上的『890. 查找和替换模式』

你有一个单词列表 words 和一个模式 pattern,你想知道 words 中的哪些单词与模式匹配。

如果存在字母的排列 p ,使得将模式中的每个字母 x 替换为 p(x) 之后,我们就得到了所需的单词,那么单词与模式是匹配的。

(回想一下,字母的排列是从字母到字母的双射:每个字母映射到另一个字母,没有两个字母映射到同一个字母。)

返回 words 中与给定模式匹配的单词列表。

你可以按任何顺序返回答案。

示例1:

输入:words = [“abc”,”deq”,”mee”,”aqq”,”dkd”,”ccc”], pattern = “abb”
输出:[“mee”,”aqq”]
解释
“mee” 与模式匹配,因为存在排列 {a -> m, b -> e, …}。
“ccc” 与模式不匹配,因为 {a -> c, b -> c, …} 不是排列。
因为 a 和 b 映射到同一个字母。

提示
  • 1 <= words.length <= 50
  • 1 <= pattern.length = words[i].length <= 20

题解

设 $words$ 中某一个字符串 $word$ 的字符集为 $X$,$pattern$ 的字符集为 $Y$,题目要求我们定义一个双射 $f(X)\mapsto Y$。
使用一个哈希表来记录 $X$ 到 $Y$ 的映射,为了满足单射,需要一个数组来记录 $Y$ 中字符是否已经被映射,同时检查相同的的字符映射的字符是否相同。由于两个字符串等长,容易证明满足上述条件的单射是一个满射。

代码

class Solution {
public:
    vector<string> findAndReplacePattern(vector<string>& words, string pattern) {
        int mp[26], visited[26];
        vector<string> ans;
        for (const auto& word: words) {
            fill(mp, mp + 26, -1);
            fill(visited, visited + 26, 0);
            int n = word.size();
            int i = 0;
            for (; i < n; ++i) {
                int idx1 = word[i] - 'a', idx2 = pattern[i] - 'a';
                if (mp[idx1] == -1 && !visited[idx2]) {
                    mp[idx1] = idx2;
                    visited[idx2] = 1;
                } else if (mp[idx1] != idx2) {
                    break;
                }
            }
            if (i == n) {
                ans.emplace_back(word);
            }
        }
        return ans;
    }
};

复杂度分析

  • 时间复杂度:$O(mn+mC)$,$m$ 是 $words$ 的长度,$n$ 是每个字符串的长度,$C$ 是字符的个数此处为 $26$。
  • 空间复杂度:$O(C)$

文章作者: xitie2000
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 xitie2000 !
评论
  目录