Given a List of words, return the words that can be typed using letters of alphabet on only one row's of American keyboard like the image below.
Input: ["Hello", "Alaska", "Dad", "Peace"] Output: ["Alaska", "Dad"]
题意:给一个字符串表,返回所有满足串内字母都在键盘上同一行的字符串。只需要考虑字符串内只有字母,当然包括大写和小写字母。
基本思路:
1.根据键盘的样子把52个字母(大小写)分成3组:然后去按字符串去判断每个字母是否都属于首字母所在字母组,如果是就将结果保存在结果组,如果否就查找下一个。简单粗暴的方法。
1 class Solution { 2 public: 3 vector<string> findWords(vector<string>& words) { 4 unordered_set<char> set1 = {'Q','q','W','w','E','e','R','r','T','t','Y','y','U','u','I','i','O','o','P','p'}; 5 unordered_set<char> set2 = {'S','s','D','d','F','f','G','g','H','h','J','j','K','k','L','l','a','A'}; 6 unordered_set<char> set3 = {'Z','z','X','x','C','c','V','v','B','b','N','n','M','m'}; 7 vector<unordered_set<char>> sets = {set1, set2, set3}; 8 vector<string> result; 9 for(auto & elem:words) 10 { 11 int index = 0, flag = 0; 12 if(set2.find(elem[0]) != set2.end()) 13 index = 1; 14 else if(set3.find(elem[0]) != set3.end()) 15 index = 2; 16 unordered_set<char> temp = sets[index]; 17 for(auto & c:elem) 18 { 19 if(temp.find(c) == temp.end()) 20 { 21 flag = 1; 22 break; 23 } 24 } 25 if(!flag) 26 result.push_back(elem); 27 } 28 return result; 29 } 30 };
2. 上面代码看上去令人烦躁的点有几个:1>是大小写字母都查了一遍,解决方案:把查询字符串先处理下让它全是小/大写字母; 2> 每次判断都要去容器中进行查找,时间复杂度高。因此改进代码如下:
1 class Solution { 2 public: 3 vector<string> findWords(vector<string>& words) { 4 vector<int> v1(26); 5 vector<string> dict = {"QWERTYUIOP", "ASDFGHJKL", "ZXCVBNM"},ret; 6 int bit =0; 7 for(auto & elem:dict){ 8 for(char & c: elem) v1[c-'A'] = 1<<bit; 9 ++bit; 10 } 11 for(auto & word:words){ 12 int flag = 7; 13 for(char & c:word) 14 if((flag &= v1[toupper(c)-'A']) == 0) break; 15 if(flag) ret.push_back(word); 16 } 17 return ret; 18 } 19 };
参考LeetCode Hcisly 的做法完成。
由于c++本身没有正则表达式库文件,所以没法使用正则表达式做这道题,但是可以使用Python的方式写一个(看上去)简单的方法。
1 def findwords(self,words): 2 return filter(re.compile('(?i)([qwertyuiop]*|[asdfghjkl]*|[zxcvbnm]*)$').match, words)
然而实际消耗时间相当于上面c++的几十倍。
来自一个还没tu的fgo玩家和前DOTA2非职业选手