An abbreviation of a word follows the form <first letter><number><last letter>. Below are some examples of word abbreviations:
a) it --> it (no abbreviation)
1
b) d|o|g --> d1g
1 1 1
1---5----0----5--8
c) i|nternationalizatio|n --> i18n
1
1---5----0
d) l|ocalizatio|n --> l10n
Assume you have a dictionary and given a word, find whether its abbreviation is unique in the dictionary. A word's abbreviation is unique if no other word from the dictionary has the same abbreviation.
Example:
Given dictionary = [ "deer", "door", "cake", "card" ]
isUnique("dear") -> false
isUnique("cart") -> true
isUnique("cane") -> false
isUnique("make") -> true
這道題讓我們求獨特的單詞縮寫,但是題目中給的例子不是很清晰,來看下面三種情況:
1. dictionary = {"dear"}, isUnique("door") -> false
2. dictionary = {"door", "door"}, isUnique("door") -> true
3. dictionary = {"dear", "door"}, isUnique("door") -> false
從上面三個例子可以看出,當縮寫一致的時候,字典中的單詞均和給定單詞相同時,返回 true。這里需要用 HashMap 來建立縮寫形式和其對應的單詞的映射,把所有縮寫形式的相同單詞放到一個 HashSet 中,然后再判斷是否 unique 的時候只需要看給定單詞的縮寫形式的 HashSet 里面該單詞的個數是否和 HashSet 中的元素總數相同,相同的話就是上面的第二種情況,返回 true。需要注意的是由於 HashSet 中不能有重復值,所有上面第二種情況只會有一個 door 存在 HashSet 里,但是並不影響判斷結果,參見代碼如下:
解法一:
class ValidWordAbbr { public: ValidWordAbbr(vector<string>& dictionary) { for (auto a : dictionary) { string k = a; if (a.size() > 2) k = a[0] + to_string(a.size() - 2) + a.back(); m[k].insert(a); } } bool isUnique(string word) { string k = word; if (word.size() > 2) k = word[0] + to_string(word.size() - 2) + word.back(); return m[k].count(word) == m[k].size(); } private: unordered_map<string, unordered_set<string>> m; };
如果我們想省一些空間,也可以不用 HashSet,但如何區分上面的第二和第三種情況呢,在遇到 HashMap 中沒有當前縮寫形式的時候,將該縮寫形式和當前單詞建立映射,如果該縮寫形式應經存在,那么看如果映射的單詞不是當前單詞,將映射單詞改為空字符串,這樣做的原因是,在對於第三種情況 dictionary = {"dear", "door"} 時,遍歷 dear 時,建立 d2r 和 dear 的映射,當遍歷到 door 的時候,由於 door 和 dear 不同,將映射改為 d2r 和 "" 映射,而對於第二種情況 dictionary = {"door", "door"},保留 d2r 和 door 的映射,那么這樣在判斷 door 是否 unique 時,就可以區別第二種和第三種情況了,參見代碼如下:
解法二:
class ValidWordAbbr { public: ValidWordAbbr(vector<string>& dictionary) { for (auto a : dictionary) { string k = a; if (a.size() > 2) k = a[0] + to_string(a.size() - 2) + a.back(); if (m.find(k) != m.end() && m[k] != a) m[k] = ""; else m[k] = a; } } bool isUnique(string word) { string k = word; if (word.size() > 2) k = word[0] + to_string(word.size() - 2) + word.back(); return m.find(k) == m.end() || m[k] == word; }
private: unordered_map<string, string> m; };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/288
類似題目:
Two Sum III - Data structure design
參考資料:
https://leetcode.com/problems/unique-word-abbreviation/
https://leetcode.com/problems/unique-word-abbreviation/discuss/73133/8-lines-in-C%2B%2B...
