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 映射到同一个字母。
详见代码注释:
import java.util.ArrayList;
import java.util.List;
/**
* 思路:数组模拟Map操作进行映射(即map[p] -> word[s]),一边映射一边检查映射
*
* 步骤
* 1.首先判断长度,显然,长度不同无法映射
* 2.将word与pattern 进行映射:设s为word[i], p为pattern[i]
* 如果map[p]为0且s没有被映射
* map[p] = s; s标记被映射
* 如果map[p]不为0,则已经映射出去
* 则检查map[p]是否映射为当前s, 不等则false
* return
*
* 注意:因为是双射,所以谁向谁映射无所谓
*/
class Solution_890 {
public boolean isMatch(String word, String pattern) {
int[] map = new int[138];
int[] isUse = new int[138]; //因为是双射 所以需要标记是否被匹配过(boolean also OK)
for (int i = 0; i < word.length(); i++) {
int p = pattern.charAt(i);
int s = word.charAt(i);
if (map[p] == 0 && isUse[s] == 0) { //源字符没匹配过
map[p] = s;
isUse[s] = 1; //进行匹配且进行映射
} else if (map[p] != s) { // 如果arr[p[i]]不为0 那么之前肯定已经映射过 如果不相等 返回false
return false;
}
}
return true;
}
public List<String> findAndReplacePattern(String[] words, String pattern) {
List<String> lst = new ArrayList<>();
for (int i = 0; i < words.length; i++) {
if (words[i].length() == pattern.length()) { //长度不同直接pass
if (isMatch(words[i], pattern))
lst.add(words[i]);
}
}
return lst;
}
}
//test
public class _890 {
public static void main(String[] args) {
String[] arr = {"abc", "deq", "mee", "aqq", "dkd", "ccc"};
String pattern = "abb";
Solution_890 solution = new Solution_890();
System.out.println(solution.findAndReplacePattern(arr, pattern));
}
}