500. 键盘行
题目描述
给你一个字符串数组 words ,只返回可以使用在 美式键盘 同一行的字母打印出来的单词。键盘如下图所示。
请注意,字符串 不区分大小写,相同字母的大小写形式都被视为在同一行。
美式键盘 中:
- 第一行由字符
"qwertyuiop"组成。 - 第二行由字符
"asdfghjkl"组成。 - 第三行由字符
"zxcvbnm"组成。
示例 1:
输入:words = ["Hello","Alaska","Dad","Peace"]
输出:["Alaska","Dad"]
解释:
由于不区分大小写,"a" 和 "A" 都在美式键盘的第二行。
示例 2:
输入:words = ["omk"]
输出:[]
示例 3:
输入:words = ["adsdf","sfd"]
输出:["adsdf","sfd"]
提示:
1 <= words.length <= 201 <= words[i].length <= 100words[i]由英文字母(小写和大写字母)组成
解法
方法一:集合判断
思考
若逐行扫描每个单词的每个字母,并与三行键盘字符比对,总代价与字母数成正比,在本题规模下可行。反复对同一行做成员判断,会把行内字符集构造多次。
注意到判定只依赖「字母集合是否落在某一行」,与字母顺序无关。为此把三行做成集合,将单词转成小写后取集合,再判断是否为某一行的子集。一次遍历即可筛出全部合法单词。
把三行键盘分别做成集合。对每个单词,把它的字母集合与三行比较,若是其中某一行的子集,则加入答案。
时间复杂度 \(O(L)\),空间复杂度 \(O(C)\)。其中 \(L\) 为所有字符串的长度之和;而 \(C\) 为字符集的大小,本题中 \(C = 26\)。
1 2 3 4 5 6 7 8 9 10 11 | |
方法二:字符映射
思考
集合判断已经是线性扫描,但每个单词都要新建集合并做三次子集比较,常数偏大。
将二十六字母预先映射到行号后,只需核对单词内所有字母是否与首字母同行。映射表长度为字符集大小,判断仍是一遍扫描,实现更直接。
将每个键盘行的字符映射到对应的行号,再判断单词中所有字母是否落在同一行。
时间复杂度 \(O(L)\),空间复杂度 \(O(C)\)。其中 \(L\) 为所有字符串的长度之和;而 \(C\) 为字符集的大小,本题中 \(C = 26\)。
1 2 3 4 5 6 7 8 9 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
