890.查找和替换模式
你有一个单词列表 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 映射到同一个字母。
利用哈希表构造映射模拟过程
给定字符串数组中的字符串如果和模式字符串形成双映射的话则该字符串与模式是匹配的,双射的意思是一个字母和一个字母唯一对应,是双向的,由此我们易想到使用两个哈希表构造映射关系模拟该过程。
而这个过程又可以优化为使用数组来代替哈希表,因为本题中只有小写字母,可以用有限空间表示,如果是任意字符的话就必须使用哈希表了。
如果是任意字符,也可以使用一个Map和一个Set实现,使用Map构造单射,此时将加入Map的value放入Set中,如果遍历到的字符没有在Map的Key中,还需要判断对应模式的字符是否已经被使用过,也就是是否在Set中,如果Key不存在而模式中对应字符被使用过,该字符串也是不匹配的。
使用一个变量判断字符串是否遍历完,遍历完则加入结果,每次遍历一个字符串都要进行初始化。
class Solution { public List<String> findAndReplacePattern(String[] words, String pattern) { LinkedList<String> res = new LinkedList<>(); Map<Character, Character> map = new HashMap<>(); int[] visited = new int[26]; //Set for (String s : words) { int time = 0; //记录s是否被遍历完 for (int i = 0; i < s.length(); i++, time++) { if (map.containsKey(s.charAt(i))) { //如果Key存在 if (map.get(s.charAt(i)) == pattern.charAt(i)) { //匹配则遍历下一个字符 continue; }else { //不匹配直接开始遍历下一个字符串 break; } }else { //viseted.contains(pattern.charAt(i)) if (visited[pattern.charAt(i) - 'a'] == -1) { //如果Key不存在且对应模式的字符使用过则该字符串不匹配 break; } map.put(s.charAt(i), pattern.charAt(i)); //Key不存在且对应模式的字符未使用过 //viseted.add(pattern.charAt(i)) visited[pattern.charAt(i) - 'a'] = -1; //标记该字符,也可以用Set } } if (time == s.length()) { //字符串匹配加入结果 res.add(new String(s)); } time = 0; //初始化 map.clear(); for (int i = 0; i < 26; i++) { visited[i] = 0; } } return res; } }
原文:https://leetcode.cn/problems/find-and-replace-pattern/solution/by-nice-hermann9a2-bo9z/