Easy
题目描述
给定一种规律 pattern 和一个字符串 s,判断 s 是否遵循相同的规律。
这里的「遵循」指完全匹配,例如,pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。具体来说:
pattern中的每个字母都映射到s中的一个唯一单词。s中的每个唯一单词都映射到pattern中的一个字母。- 不能有两个字母映射到同一个单词,也不能有两个单词映射到同一个字母。
示例 1:
输入: pattern = "abba", s = "dog cat cat dog"
输出: true
解释:
双射可以按如下方式建立:
'a' 映射到 "dog"。
'b' 映射到 "cat"。
示例 2:
输入: pattern = "abba", s = "dog cat cat fish"
输出: false
示例 3:
输入: pattern = "aaaa", s = "dog cat cat dog"
输出: false
提示:
1 <= pattern.length <= 300pattern只包含小写英文字母1 <= s.length <= 3000s只包含小写英文字母和空格' 's不包含任何前导或尾随对空格s中每个单词都被单个空格分隔
解题思路
这是一道典型的双向映射问题,需要建立字符与单词之间的一一对应关系。
核心思路: 使用两个哈希表分别维护从字符到单词和从单词到字符的映射关系。在遍历过程中,检查每次映射是否与已建立的映射关系冲突。
算法步骤:
- 首先将字符串
s按空格分割成单词数组 - 检查模式字符串长度与单词数组长度是否相等,不等则直接返回
false - 使用两个哈希表:
charToWord: 存储字符到单词的映射wordToChar: 存储单词到字符的映射
- 遍历模式字符串和单词数组:
- 如果字符已存在映射,检查是否映射到当前单词
- 如果单词已存在映射,检查是否映射到当前字符
- 如果都不存在映射,建立新的双向映射
- 任何冲突都返回
false
- 遍历完成后返回
true
时间复杂度分析: 需要遍历一次模式字符串,每次哈希表操作为 O(1),总体为 O(n)。 空间复杂度分析: 需要存储两个哈希表和分割后的单词数组,为 O(n)。
代码实现
class Solution {
public:
bool wordPattern(string pattern, string s) {
vector<string> words;
stringstream ss(s);
string word;
while (ss >> word) {
words.push_back(word);
}
if (pattern.length() != words.size()) {
return false;
}
unordered_map<char, string> charToWord;
unordered_map<string, char> wordToChar;
for (int i = 0; i < pattern.length(); i++) {
char c = pattern[i];
string w = words[i];
if (charToWord.count(c)) {
if (charToWord[c] != w) {
return false;
}
} else {
charToWord[c] = w;
}
if (wordToChar.count(w)) {
if (wordToChar[w] != c) {
return false;
}
} else {
wordToChar[w] = c;
}
}
return true;
}
};
class Solution:
def wordPattern(self, pattern: str, s: str) -> bool:
words = s.split()
if len(pattern) != len(words):
return False
char_to_word = {}
word_to_char = {}
for i in range(len(pattern)):
c = pattern[i]
w = words[i]
if c in char_to_word:
if char_to_word[c] != w:
return False
else:
char_to_word[c] = w
if w in word_to_char:
if word_to_char[w] != c:
return False
else:
word_to_char[w] = c
return True
public class Solution {
public bool WordPattern(string pattern, string s) {
string[] words = s.Split(' ');
if (pattern.Length != words.Length) {
return false;
}
Dictionary<char, string> charToWord = new Dictionary<char, string>();
Dictionary<string, char> wordToChar = new Dictionary<string, char>();
for (int i = 0; i < pattern.Length; i++) {
char c = pattern[i];
string w = words[i];
if (charToWord.ContainsKey(c)) {
if (charToWord[c] != w) {
return false;
}
} else {
charToWord[c] = w;
}
if (wordToChar.ContainsKey(w)) {
if (wordToChar[w] != c) {
return false;
}
} else {
wordToChar[w] = c;
}
}
return true;
}
}
var wordPattern = function(pattern, s) {
const words = s.split(' ');
if (pattern.length !== words.length) {
return false;
}
const charToWord = new Map();
const wordToChar = new Map();
for (let i = 0; i < pattern.length; i++) {
const c = pattern[i];
const w = words[i];
if (charToWord.has(c)) {
if (charToWord.get(c) !== w) {
return false;
}
} else {
charToWord.set(c, w);
}
if (wordToChar.has(w)) {
if (wordToChar.get(w) !== c) {
return false;
}
} else {
wordToChar.set(w, c);
}
}
return true;
};
复杂度分析
| 复杂度 | 大小 |
|---|---|
| 时间复杂度 | O(n) |
| 空间复杂度 | O(n) |
其中 n 为模式字符串的长度。时间复杂度主要来自于遍历模式字符串和单词数组,空间复杂度主要来自于存储两个哈希表和分割后的单词数组。
相关题目
. Isomorphic Strings (Easy)
. Word Pattern II (Medium)
. Find and Replace Pattern (Medium)