持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情
刷题的日常
一天一题,保持脑子清爽
查找和替换模式
来自leetcode的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 映射到同一个字母。
理解题意
有点类似与正则匹配
- pattern的字符可以映射为任意其它字符
- 已经被映射过的不能重新映射
- 数量必须要一致
做题思路
其实很简单
- 开辟个Hash表保存pattern的映射关系
- 已经映射的字符不能重复映射,所以我们需要再开辟个Hash表保存已经映射过的pattern字符
- 遍历words数组
- 如果字符串长度不相等,则不能映射
- 如果映射没有重复,并且符合pattern的规则,这添加进结果集
- 返回结果列表
代码实现
需要遍历数组,并且校验字符串,假设字符串最大长度为m,words的长度为n,则复杂度为O(m * n),代码如下:
public class Solution {
public List<String> findAndReplacePattern(String[] words, String pattern) {
List<String> result = new LinkedList<>();
Map<Character, Character> map = new HashMap<>(pattern.length());
Map<Character, Character> reMap = new HashMap<>(pattern.length());
for (String word : words) {
if (checkPattern(word, pattern, map, reMap)) {
result.add(word);
}
}
return result;
}
private boolean checkPattern(String word, String pattern, Map<Character, Character> map, Map<Character, Character> reMap) {
if (word.length() != pattern.length()) {
return false;
}
map.clear();
reMap.clear();
for (int i = 0; i < pattern.length(); i++) {
char pC = pattern.charAt(i);
char wC = word.charAt(i);
Character mC = map.get(pC);
if (mC != null && mC != wC) {
return false;
}
Character c = reMap.get(wC);
if (c != null && c != pC) {
return false;
}
map.put(pC, wC);
reMap.put(wC, pC);
}
return true;
}
}