文章目录
- 题目
- 标题和出处
- 难度
- 题目描述
- 要求
- 示例
- 数据范围
- 解法
- 思路和算法
- 代码
- 复杂度分析
题目
标题和出处
标题:键盘行
出处:500. 键盘行
难度
2 级
题目描述
要求
给你一个字符串数组 words \texttt{words} words,只返回可以使用在美式键盘同一行的字母打印出来的单词。键盘如下图所示。
美式键盘中:
- 第一行由字符 "qwertyuiop" \texttt{"qwertyuiop"} "qwertyuiop" 组成。
- 第二行由字符 "asdfghjkl" \texttt{"asdfghjkl"} "asdfghjkl" 组成。
- 第三行由字符 "zxcvbnm" \texttt{"zxcvbnm"} "zxcvbnm" 组成。
示例
示例 1:
输入:
words
=
["Hello","Alaska","Dad","Peace"]
\texttt{words = ["Hello","Alaska","Dad","Peace"]}
words = ["Hello","Alaska","Dad","Peace"]
输出:
["Alaska","Dad"]
\texttt{["Alaska","Dad"]}
["Alaska","Dad"]
示例 2:
输入:
words
=
["omk"]
\texttt{words = ["omk"]}
words = ["omk"]
输出:
[]
\texttt{[]}
[]
示例 3:
输入:
words
=
["adsdf","sfd"]
\texttt{words = ["adsdf","sfd"]}
words = ["adsdf","sfd"]
输出:
["adsdf","sfd"]
\texttt{["adsdf","sfd"]}
["adsdf","sfd"]
数据范围
- 1 ≤ words.length ≤ 20 \texttt{1} \le \texttt{words.length} \le \texttt{20} 1≤words.length≤20
- 1 ≤ words[i].length ≤ 100 \texttt{1} \le \texttt{words[i].length} \le \texttt{100} 1≤words[i].length≤100
- words[i] \texttt{words[i]} words[i] 由英语字母(小写和大写字母)组成
解法
思路和算法
为了判断一个单词是否由键盘同一行的字母组成,需要预处理每个字母所在的键盘行,可以使用哈希表记录每个字母所在的键盘行的编号。
一个单词由键盘同一行的字母组成,等价于该单词的任意两个字母所在的键盘行的编号相同,因此在判断一个单词是否由键盘同一行的字母组成时,可以首先得到该单词的首字母所在的键盘行的编号,然后判断该单词的其余每个字母所在的键盘行的编号是否和该单词的首字母所在的键盘行的编号相同。
实现方面,由于每个单词都由英语字母组成,因此可以使用长度为 26 26 26 的数组代替哈希表。由于单词中可能有小写和大写字母,因此在记录和判断每个字母所在的键盘行的编号时,需要首先将字母转成小写字母,然后进行相应的操作。
代码
class Solution {
public String[] findWords(String[] words) {
String[] lettersEachRow = {"qwertyuiop", "asdfghjkl", "zxcvbnm"};
int rows = lettersEachRow.length;
int[] map = new int[26];
for (int i = 0; i < rows; i++) {
String letters = lettersEachRow[i];
int lettersCount = letters.length();
for (int j = 0; j < lettersCount; j++) {
map[letters.charAt(j) - 'a'] = i;
}
}
List<String> rowWordsList = new ArrayList<String>();
for (String word : words) {
boolean flag = true;
int wordLength = word.length();
int row = map[Character.toLowerCase(word.charAt(0)) - 'a'];
for (int i = 1; i < wordLength; i++) {
int currRow = map[Character.toLowerCase(word.charAt(i)) - 'a'];
if (currRow != row) {
flag = false;
break;
}
}
if (flag) {
rowWordsList.add(word);
}
}
int length = rowWordsList.size();
String[] rowWords = new String[length];
for (int i = 0; i < length; i++) {
rowWords[i] = rowWordsList.get(i);
}
return rowWords;
}
}
复杂度分析
-
时间复杂度: O ( ∣ Σ ∣ + L ) O(|\Sigma| + L) O(∣Σ∣+L),其中 L L L 是数组 words \textit{words} words 中的单词长度之和, Σ \Sigma Σ 是字符集,这道题中 Σ \Sigma Σ 是全部英语字母(不区分大小写), ∣ Σ ∣ = 26 |\Sigma| = 26 ∣Σ∣=26。首先遍历全部英语字母并在哈希表中记录每个字母所在的键盘行的编号,时间复杂度是 O ( ∣ Σ ∣ ) O(|\Sigma|) O(∣Σ∣),然后遍历数组 words \textit{words} words 中的每个单词并判断是否由键盘同一行的字母组成,每个单词的每个字母都会遍历一次,时间复杂度是 O ( L ) O(L) O(L),因此总时间复杂度是 O ( ∣ Σ ∣ + L ) O(|\Sigma| + L) O(∣Σ∣+L)。
-
空间复杂度: O ( ∣ Σ ∣ ) O(|\Sigma|) O(∣Σ∣),其中 Σ \Sigma Σ 是字符集,这道题中 Σ \Sigma Σ 是全部英语字母(不区分大小写), ∣ Σ ∣ = 26 |\Sigma| = 26 ∣Σ∣=26。空间复杂度主要取决于哈希表,哈希表需要记录每个字母所在的键盘行的编号。注意返回值不计入空间复杂度。