- C++ unordered_map
- 分割字串(空格隔開)
Code
第一次解的時候的寫法,有很多的改善空間:第一點,字串分割可以用 istringstream
。第二點,map 可以用一個,也可以用兩個,重點是要檢查 pattern & string token 之間的一對一關係(不行多對一,也不行一對多)。
另外就是 if(iter < pattern.size() || iter < tokens.size() ) return false;
可以提早 check,節省時間。
class Solution {
public:
bool wordPattern(string pattern, string s) {
vector<string> tokens;
unordered_map<char, string> pts;
unordered_map<string, char> stp;
for(int i = 0; i < s.size(); i++) {
string temp = "";
while(i < s.size() && s[i] != ' ') {
temp += s[i];
i++;
}
tokens.push_back(temp);
}
int iter = 0;
while(iter < pattern.size() && iter < tokens.size()) {
if(pts.find(pattern[iter]) != pts.end()) {
if(pts[pattern[iter]] != tokens[iter]) return false;
}
if(stp.find(tokens[iter]) != stp.end()) {
if(stp[tokens[iter]] != pattern[iter]) return false;
}
stp[tokens[iter]] = pattern[iter];
pts[pattern[iter]] = tokens[iter];
iter++;
}
if(iter < pattern.size() || iter < tokens.size() ) return false;
return true;
}
};
使用 istringstream
:
class Solution {
public:
bool wordPattern(string pattern, string s) {
vector<string> tokens;
istringstream in(s); string token;
while(in >> token) {
tokens.push_back(token);
}
// early stop
if(pattern.size() != tokens.size()) return false;
unordered_map<char, string> pts;
unordered_map<string, char> stp;
for(int i = 0; i < pattern.size(); i++) {
if (pts.find(pattern[i]) != pts.end()) {
// check 1 to n
if(pts[pattern[i]] != tokens[i]) return false;
}
if (stp.find(tokens[i]) != stp.end()) {
// check n to 1
if(stp[tokens[i]] != pattern[i]) return false;
}
pts[pattern[i]] = tokens[i];
stp[tokens[i]] = pattern[i];
}
return true;
}
};
上面的解法思路都是將文字 map 到文字,但是其實可以將文字 map 到 index,這樣也可以檢查一對一的關係,因為若 pattern 和 token map 到不同 index,代表他們落在不同位置,代表是一對多或是多對一的狀況發生。
要注意這裡是 map 到 i + 1
,因為若 key 不存在時返回的值是 0
。
class Solution {
public:
bool wordPattern(string pattern, string s) {
vector<string> tokens;
istringstream in(s); string token;
while(in >> token) {
tokens.push_back(token);
}
// early stop
if(pattern.size() != tokens.size()) return false;
unordered_map<char, int> pti;
unordered_map<string, int> sti;
for(int i = 0; i < pattern.size(); i++) {
if(pti[pattern[i]] != sti[tokens[i]]) return false;
// default is 0 if key not exist!
pti[pattern[i]] = i + 1;
sti[tokens[i]] = i + 1;
}
return true;
}
};
還可以更近一步加速,用istringstream
或是 stringstream
邊讀邊判斷:
class Solution {
public:
bool wordPattern(string pattern, string s) {
istringstream ss(s);
unordered_map<char, int> pti;
unordered_map<string, int> sti;
int i = 0, n = pattern.length();
for(string token; ss >> token; i++) {
// i == n means pattern runs out first
if(i == n || pti[pattern[i]] != sti[token]) return false;
// default is 0 if key not exist!
pti[pattern[i]] = i + 1;
sti[token] = i + 1;
}
return i == n; // check if s runs out first
}
};