简单来说,题目的要求就是要我们检测 word 和
pattern
是否满足一一对应的双射关系,只需对每个单词逐字母的构建一个由
word 到 pattern
的字母映射关系,再检查该关系是否是双射即可。
这里可以有两种方法进行检查:
构建 word 到 pattern 和
pattern 到 word
的映射关系,检查二者是否都是单射。
只构建 word 到 pattern
的映射关系,检查其是否是单射并且是否有多对一的映射关系。
方法一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# Code language: Python classSolution: deffindAndReplacePattern(self, words: List[str], pattern: str) -> List[str]: ans = list() a = ord('a') for word in words: m1 = [Nonefor _ inrange(26)] m2 = [Nonefor _ inrange(26)] for i, j inzip(word, pattern): x, y = ord(i) - a, ord(j) - a if m1[x] isNone: m1[x] = y if m2[y] isNone: m2[y] = x if m1[x] != y or m2[y] != x: break else: ans.append(word) return ans
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// Code language: Java classSolution { public List<String> findAndReplacePattern(String[] words, String pattern) { List<String> ans = newArrayList<>(); intn= pattern.length(); int[] m1 = newint[26], m2 = newint[26]; loop: for (String word: words) { Arrays.fill(m1, -1); Arrays.fill(m2, -1); for (inti=0; i < n; ++i) { intx= word.charAt(i) - 'a', y = pattern.charAt(i) - 'a'; if (m1[x] == -1) m1[x] = y; if (m2[y] == -1) m2[y] = x; if (m1[x] != y || m2[y] != x) continue loop; } ans.add(word); } return ans; } }
// Code language: JavaScript /** * @param {string[]} words * @param {string} pattern * @return {string[]} */ var findAndReplacePattern = function (words, pattern) { var ans = newArray(); var n = pattern.length, m = words.length, a = 'a'.charCodeAt(0); var m1 = newArray(), m2 = newArray(); var word; for (let idx = 0; idx < m; ++idx) { word = words[idx]; for (let i = 0; i < 26; ++i) { m1[i] = -1; m2[i] = -1; } let p = true; for (let i = 0; i < n; ++i) { let x = word.charCodeAt(i) - a, y = pattern.charCodeAt(i) - a; if (m1[x] == -1) m1[x] = y; if (m2[y] == -1) m2[y] = x; if (m1[x] != y || m2[y] != x) { p = false; break; } } if (p) ans.push(word); } return ans; };
# Code language: Python classSolution: deffindAndReplacePattern(self, words: List[str], pattern: str) -> List[str]: ans = list() a = ord('a') for word in words: m = [Nonefor _ inrange(26)] for i, j inzip(word, pattern): x, y = ord(i) - a, ord(j) - a if m[x] isNone: m[x] = y if m[x] != y: break else: s = set() for t in m: if t isnotNoneand t in s: break s.add(t) else: ans.append(word) return ans
// Code language: C++ classSolution { public: vector<string> findAndReplacePattern(vector<string>& words, string pattern){ vector<string> ans; int n = pattern.size(); int m1[26], m2[26]; for (string& word: words) { memset(m1, -1, sizeof(m1)), memset(m2, -1, sizeof(m2)); bool p = true; for (int i = 0; i < n; ++i) { int x = word[i] - 'a', y = pattern[i] - 'a'; if (m1[x] == -1) m1[x] = y; if (m1[x] != y) { p = false; break; } } if (!p) continue; for (int i = 0; i < 26; ++i) { int m = m1[i]; if (m == -1) continue; if (m2[m] != -1) { p = false; break; } m2[m] = 1; } if (p) ans.emplace_back(word); } return ans; } };
时间复杂度: \(O(nm)\), 其中 \(n\) 表示最大单词长度,\(m\) 表示 words 的长度