[LeetCode] 890. Find and Replace Pattern 查找和替換模式



You have a list of words and a pattern, and you want to know which words in words matches the pattern.html

A word matches the pattern if there exists a permutation of letters p so that after replacing every letter x in the pattern with p(x), we get the desired word.git

(Recall that a permutation of letters is a bijection from letters to letters: every letter maps to another letter, and no two letters map to the same letter.)github

Return a list of the words in words that match the given pattern. 數組

You may return the answer in any order.設計

Example 1:code

Input: words = ["abc","deq","mee","aqq","dkd","ccc"], pattern = "abb"
Output: ["mee","aqq"]
Explanation: "mee" matches the pattern because there is a permutation {a -> m, b -> e, ...}.
"ccc" does not match the pattern because {a -> c, b -> c, ...} is not a permutation,
since a and b map to the same letter.

Note:orm

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



這道題給了咱們一個字符串數組 words,還有一個 pattern 單詞,問 words 數組中的單詞是否知足 pattern 的模式,並給了一個例子。好比 pattern 是 abb 的話,表示後兩個字母是相同的,好比 mee 和 aqq,那麼一個很直接的想法就是創建每一個單詞 word 和 pattern 中每一個字符之間的映射,好比 mee->abb 的話,就是 m->a, e->b,在創建映射以前要判斷,若已經存在了該映射,且映射值不是當前 pattern 中的對應字符時,就是沒法匹配的,好比 mm 和 ab,在第一次創建了 m->a 的映射,當遍歷到第二個m的時候,發現m的映射已經存在,但不是b,就不能再創建 m->b 的映射,則表示沒法匹配。分析到這裏,你可能感受沒啥問題,但其實咱們忽略一種狀況,word 和 pattern 中的每一個字符必須是一一對應的,任何一個方向的多對一都是不行了,好比 mn 和 aa,剛開始創建了 m->a 的映射,遍歷到n的時候,發現沒有n的映射,此時也不能創建 n->a 的映射,由於 pattern 中的a已經被佔用了,因此還須要一個 HashMap 來創建反方向的映射,只有兩個 HashMap 中都不存在的,才能創建映射,只要有一個已經存在了,直接 break 掉。在 for 循環結束後,看是否已經到達了 word 的末尾,沒有提早 break 掉的話,就將 word 加入結果 res 中便可,參見代碼以下:htm



解法一:blog

class Solution {
public:
    vector<string> findAndReplacePattern(vector<string>& words, string pattern) {
        vector<string> res;
        for (string word : words) {
            unordered_map<char, char> w2p, p2w;
            int i = 0, n = word.size();
            for (; i < n; ++i) {
                if (w2p.count(word[i]) && w2p[word[i]] != pattern[i]) break;
                w2p[word[i]] = pattern[i];
                if (p2w.count(pattern[i]) && p2w[pattern[i]] != word[i]) break;
                p2w[pattern[i]] = word[i];
            }
            if (i == n) res.push_back(word);
        }
        return res;
    }
};



咱們也能夠不用 HashMap,改用兩個長度爲 26 的數組,由於這道題貌似默認都是小寫字母,惟一麻煩一點的就是要把字母減去 'a' 來轉爲對應的座標,還有一點跟上面解法不一樣的地方就是,字母是跟起座標位置加1來創建映射(加1的緣由是默認值是0,而當 i=0 時爲了區分默認值,就要加1),由於兩個字母都跟一個特定的值相等,其實也等價於這兩個字母之間創建的映射(a->c, b->c => a->b)。總體思路仍是沒啥不一樣的,參見代碼以下:ci



解法二:

class Solution {
public:
    vector<string> findAndReplacePattern(vector<string>& words, string pattern) {
        vector<string> res;
        for (string word : words) {
            vector<int> w(26), p(26);
            int i = 0, n = word.size();
            for (; i < n; ++i) {
                if (w[word[i] - 'a'] != p[pattern[i] - 'a']) break;
                w[word[i] - 'a'] = p[pattern[i] - 'a'] = i + 1;
            }
            if (i == n) res.push_back(word);
        }
        return res;
    }
};



在論壇上又看到了一種解法,這種解法至關於把全部的單詞都轉爲了一種特定的模式,具體來講,就是用一個 HashMap,創建每一個字母跟其以前出現過的字母種類個數以前的映射,好比 mee->011,aqq->011,這樣相同的模式映射的值是同樣的,具體的作法是若當前字母沒有出現過,則創建和當前 HashMap 中的映射個數之間的映射,是一種很巧妙的設計思路,只不過最後又給每一個數字加上了 'a',轉爲了字母的 pattern,即 mee->abb,aqq->abb,參見代碼以下:



解法三:

class Solution {
public:
    vector<string> findAndReplacePattern(vector<string>& words, string pattern) {
        vector<string> res;
        for (string word : words) {
            if (helper(word) == helper(pattern)) res.push_back(word);
        }
        return res;
    }
    string helper(string word) {
        unordered_map<char, int> m;
        for (char c : word) {
            if (!m.count(c)) m[c] = m.size();
        }
        for (int i = 0; i < word.size(); ++i) word[i] = 'a' + m[word[i]];
        return word;
    }
};



Github 同步地址:

https://github.com/grandyang/leetcode/issues/890



相似題目:

Repeated Substring Pattern

132 Pattern

Word Pattern II

Word Pattern



參考資料:

https://leetcode.com/problems/find-and-replace-pattern/

https://leetcode.com/problems/find-and-replace-pattern/discuss/161266/JAVA-3ms-Clear-Code

https://leetcode.com/problems/find-and-replace-pattern/discuss/161288/C%2B%2BJavaPython-Normalise-Word



LeetCode All in One 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索