Given a pattern
and a string str
, find if str
follows the same pattern.
Here follow means a full match, such that there is a bijection between a letter in pattern
and a non-empty word in str
.
Example 1:
Input: pattern ="abba"
, str ="dog cat cat dog"
Output: true
Example 2:
Input:pattern ="abba"
, str ="dog cat cat fish"
Output: false
Example 3:
Input: pattern ="aaaa"
, str ="dog cat cat dog"
Output: false
Example 4:
Input: pattern ="abba"
, str ="dog dog dog dog"
Output: false
Notes:
You may assume pattern
contains only lowercase letters, and str
contains lowercase letters separated by a single space.
Credits:
Special thanks to @minglotus6 for adding this problem and creating all test cases.
這道題給我們一個模式字符串,又給我們一個單詞字符串,讓我們求單詞字符串中單詞出現的規律是否符合模式字符串中的規律。那么首先想到就是用 HashMap 來做,建立模式字符串中每個字符和單詞字符串每個單詞之間的映射,而且這種映射必須是一對一關系的,不能 'a' 和 'b' 同時對應 'dog',也不能 'a' 同時對應到 'dog' 和 'cat',所以我們在碰到一個新字符時,首先檢查其是否在 HashMap 中出現,若出現,其映射的單詞若不是此時對應的單詞,則返回 false。如果沒有在 HashMap 中出現,我們還要遍歷一遍 HashMap,看新遇到的單詞是否已經是其中的映射,若已經有其他映射,直接返回 false,如果沒有,再跟新遇到的字符建立映射。最后循環退出后,要檢查此時的 i 是否和 n 相同,這是檢查一對一映射的最后一步,因為當 str 中的單詞處理完了之后,pattern 中就不能有多余的字符了,參見代碼如下:
解法一:
class Solution { public: bool wordPattern(string pattern, string str) { unordered_map<char, string> m; istringstream in(str); int i = 0, n = pattern.size(); for (string word; in >> word; ++i) { if (i >= n) continue; if (m.count(pattern[i])) { if (m[pattern[i]] != word) return false; } else { for (auto a : m) { if (a.second == word) return false; } m[pattern[i]] = word; } } return i == n; } };
當然這道題也可以用兩個 HashMap 來完成,分別將字符和單詞都映射到當前的位置加1,注意這里需要加1就是為了避免默認映射值0,因為 C++ 中的 HashMap 的機制是若訪問一個不存在的 key 值,會默認建立一個映射值為0的映射。那么我們在遇到新字符和單詞時,首先看 i 是否已經是 n 了,若相等了,說明此時 pattern 中的字符已經用完了,而 str 中還有多余的單詞,這樣是無法建立一對一映射的,直接返回 false。還有當兩個 HashMap 的映射值不相同時也返回 false,否則我們同時建立單詞和 pattern 字符和當前位置加1之間的映射,循環推出后還是要檢測 i 是否和 n 相等,參見代碼如下:
解法二:
class Solution { public: bool wordPattern(string pattern, string str) { unordered_map<char, int> m1; unordered_map<string, int> m2; istringstream in(str); int i = 0, n = pattern.size(); for (string word; in >> word; ++i) { if (i == n || m1[pattern[i]] != m2[word]) return false; m1[pattern[i]] = m2[word] = i + 1; } return i == n; } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/290
類似題目:
參考資料:
https://leetcode.com/problems/word-pattern/
https://leetcode.com/problems/word-pattern/discuss/73402/8-lines-simple-Java
https://leetcode.com/problems/word-pattern/discuss/73409/Short-C%2B%2B-read-words-on-the-fly