你有一个单词列表 words 和一个模式 pattern,你想知道 words 中的哪些单词与模式匹配。
如果存在字母的排列 p ,使得将模式中的每个字母 x 替换为 p(x) 之后,我们就得到了所需的单词,那么单词与模式是匹配的。
(回想一下,字母的排列是从字母到字母的双射:每个字母映射到另一个字母,没有两个字母映射到同一个字母。)
返回 words 中与给定模式匹配的单词列表。
你可以按任何顺序返回答案。
示例:
输入: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
class Solution {public List<String> findAndReplacePattern(String[] words, String pattern) {//map 存 模板的相同字母的下标Map<Character, List<Integer>> map = new HashMap<>();int m = pattern.length();for (int i = 0; i < m; ++i) {List<Integer> list = map.get(pattern.charAt(i));if (list == null) list = new ArrayList<>();list.add(i);map.put(pattern.charAt(i), list);}List<String> res = new ArrayList<>();//illegal 是因为lambda表达式只能用final变量,所以不能判断当前s是否合法,所以不合法就加到illegalSet<String> illegal = new HashSet<>();for (String s : words) {int n = s.length();Set<Character> set = new HashSet<>();final boolean flag = true;map.forEach((key, list) -> {int size = list.size();//只有一个下标,只需要判断是不是set是否存在该值char c = s.charAt(list.get(0));if (size == 1) {if (set.contains(c)) {illegal.add(s);return;}set.add(c);} else {if (set.contains(c)) {illegal.add(s);return;}set.add(c);for (int i = 1; i < size; ++i) {if (s.charAt(list.get(i)) != c) {illegal.add(s);return;}}}});}//排除illegal的就是答案for (String s : words)if (!illegal.contains(s)) res.add(s);return res;}}
class Solution {public List<String> findAndReplacePattern(String[] ws, String pe) {List<String> ans = new ArrayList<>();int[] map = new int[26], vis = new int[26];for (String s : ws) {Arrays.fill(map, -1);Arrays.fill(vis, 0);boolean ok = true;for (int i = 0; i < pe.length() && ok; i++) {int c1 = s.charAt(i) - 'a', c2 = pe.charAt(i) - 'a';if (map[c1] == -1 && vis[c2] == 0) {map[c1] = c2; vis[c2] = 1;} else if (map[c1] != c2) ok = false;}if (ok) ans.add(s);}return ans;}}
