Keyboard Row
Problem
Given an array of strings words, return the words that can be typed using letters from only one row of an American QWERTY keyboard.
words = ["Hello", "Alaska", "Dad", "Peace"]["Alaska", "Dad"]def find_words(words):
rows = ["qwertyuiop", "asdfghjkl", "zxcvbnm"]
letter_row = {}
for i, r in enumerate(rows):
for ch in r: letter_row[ch] = i
out = []
for w in words:
lw = w.lower()
if len({letter_row[ch] for ch in lw}) == 1:
out.append(w)
return out
function findWords(words) {
const rows = ["qwertyuiop", "asdfghjkl", "zxcvbnm"];
const letterRow = {};
rows.forEach((r, i) => { for (const c of r) letterRow[c] = i; });
return words.filter(w => {
const lw = w.toLowerCase();
const seen = new Set();
for (const c of lw) seen.add(letterRow[c]);
return seen.size === 1;
});
}
class Solution {
public String[] findWords(String[] words) {
String[] rows = {"qwertyuiop", "asdfghjkl", "zxcvbnm"};
int[] map = new int[26];
for (int i = 0; i < rows.length; i++)
for (char c : rows[i].toCharArray()) map[c - 'a'] = i;
List<String> out = new ArrayList<>();
for (String w : words) {
String lw = w.toLowerCase();
int row = map[lw.charAt(0) - 'a'];
boolean ok = true;
for (char c : lw.toCharArray()) if (map[c - 'a'] != row) { ok = false; break; }
if (ok) out.add(w);
}
return out.toArray(new String[0]);
}
}
vector<string> findWords(vector<string>& words) {
string rows[3] = {"qwertyuiop", "asdfghjkl", "zxcvbnm"};
int map[26];
for (int i = 0; i < 3; i++) for (char c : rows[i]) map[c - 'a'] = i;
vector<string> out;
for (auto& w : words) {
int row = map[tolower(w[0]) - 'a'];
bool ok = true;
for (char c : w) if (map[tolower(c) - 'a'] != row) { ok = false; break; }
if (ok) out.push_back(w);
}
return out;
}
Explanation
A QWERTY keyboard has exactly three rows of letters. A word "belongs" to a single row only if every letter in it lives on that same row. So the real question for each word is simply: do all its letters come from one row?
To answer that fast, we first build a lookup table letter_row that maps each letter to its row number (0, 1, or 2). We do this once by walking the three row strings "qwertyuiop", "asdfghjkl", "zxcvbnm".
For each word, we lowercase it and collect the set of row numbers its letters use. If that set has size 1, every letter shared the same row, so we keep the word. Using a set automatically removes duplicate row numbers, so we just check how many distinct rows appeared.
Example: for "Dad" the letters d, a, d all map to row 1, so the set is {1} with size 1 — keep it. For "Hello", h is on row 1 but e is on row 0, so the set grows to {0, 1} with size 2 — drop it.
Because each letter is looked up in constant time, the whole thing runs in time proportional to the total number of letters across all words.