持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第 2 天,点击查看活动详情
题目链接
题目描述
给你一个字符串数组 words ,只返回可以使用在 美式键盘 同一行的字母打印出来的单词。键盘如下图所示。
美式键盘 中:
第一行由字符 "qwertyuiop" 组成。 第二行由字符 "asdfghjkl" 组成。 第三行由字符 "zxcvbnm" 组成。
测试用例
用例1:
输入: words = ["Hello","Alaska","Dad","Peace"]
输出: ["Alaska","Dad"]
限制
1 <= words.length <= 201 <= words[i].length <= 100words[i]由英文字母(小写和大写字母)组成
题目分析
题目会为我们提供一个单词的数组 words,需要我们判断词组中的每一个单词,他的字符是否都是在同一列。值得注意的是,单词是包括大小写的,而题目所提供的字符,都是小写。。
考虑到需要频繁的检索判断,我们使用 3 个 Set 去分别存储每一行的大小写字符;在遍历单词的每个字符之前,我们先去检查这个单词的第一个字符,判断其应该使用哪一个 Set 去检查这个单词的全部字符;当检查通过时,就记录下这个单词并在最后一起返回
代码实现
完整的代码实现如下
/**
* @param {string[]} words
* @return {string[]}
*/
var findWords = function(words) {
let lines = [new Set('qwertyuiopQWERTYUIOP'.split('')),
new Set('asdfghjklASDFGHJKL'.split('')),
new Set('zxcvbnmZXCVBNM'.split(''))
];
let arr = [];
for (let i = 0; i < words.length; i++) {
let c = words[i];
let findLine;
for (let j = 0; j < lines.length; j++) {
if (lines[j].has(c.charAt(0))) {
findLine = lines[j];
break;
}
}
let flag = true;
for (let j = 0; j < c.length; j++) {
if(!findLine.has(c.charAt(j))){
flag = false;
break;
}
}
if(flag){
arr.push(c)
}
}
return arr;
};
解法 2
另一种更加巧妙的解法用到了 Map 的特性
我们为每一行的字符,指定一个值,例如,第一行的字符,其值都是 0,第二行的字符,值都为 1,第三行的,都为 2
然后,我们遍历并替换字符,并在最后用 Set 存下来,去重,当 Set 中的元素个数 >1 时,这个单词不满足要求
/**
* @param {string[]} words
* @return {string[]}
*/
var findWords = function(words) {
let obj = {};
let strs = ['qwertyuiopQWERTYUIOP','asdfghjklASDFGHJKL','zxcvbnmZXCVBNM'];
for(let i = 0;i<strs.length;i++){
let str = strs[i];
for(let j = 0;j<str.length;j++){
obj[str.charAt(j)] = i;
}
}
let arr = [];
let set;
for (let i = 0; i < words.length; i++) {
set = new Set();
for(let j = 0;j<words[i].length;j++){
set.add(obj[words[i].charAt(j)])
}
if(set.size == 1){
arr.push(words[i])
}
}
return arr;
};