题目描述#
给定一个规律字符串 pattern 和一个字符串 s,判断它们是否满足同一套映射关系。
这里的关键是双向一一对应:
pattern中的每个字符都只能映射到一个唯一单词s中的每个单词也只能映射到一个唯一字符- 不能出现两个字符映射到同一个单词,也不能出现两个单词映射到同一个字符
思路#
先用 strings.Split 按空格拆出所有单词。如果单词数量和 pattern 的长度不一致,那么肯定不匹配,可以直接返回 false。
接下来需要同时维护两张哈希表:
patt2s:记录某个模式字符当前映射到哪个单词s2patt:记录某个单词当前映射到哪个模式字符
遍历 pattern 的每一个位置时,取出当前字符 p 和对应单词 word。
如果 patt2s 里已经有这个字符,就检查它之前映射的单词是不是当前单词;如果不是,说明同一个字符对应了不同单词,直接返回 false。反过来,再检查 s2patt 里这个单词之前是不是已经映射给了别的字符;如果是,也要返回 false。
只有两个方向都不冲突,才能说明当前这一对映射合法。整轮遍历结束后还没有冲突,就说明整个字符串满足题意。
这个写法的重点不在于“字符能不能找到单词”,而在于“一一对应”必须双向同时成立,所以两张哈希表都不能省。
代码#
import "strings"
func wordPattern(pattern string, s string) bool {
words := strings.Split(s, " ")
if len(words) != len(pattern) {
return false
}
patt2s := make(map[byte]string)
s2patt := make(map[string]byte)
for i := 0; i < len(pattern); i++ {
word := words[i]
p := pattern[i]
if v, ok := patt2s[p]; ok {
if v != word {
return false
}
} else {
patt2s[p] = word
}
if v, ok := s2patt[word]; ok {
if v != p {
return false
}
} else {
s2patt[word] = p
}
}
return true
}