哪种代码更优?效率vs可读性——键盘单行单词匹配方案抉择
代码方案抉择:高效但冗长 vs 简洁但稍慢?
我用两种方法解决了同一个编程问题,现在纠结该选哪种方案。第一种方法时间复杂度更低,少一层循环,但代码冗长杂乱;第二种用了三层循环,效率稍低,但代码简洁很多。想请教到底该优先选高效但难读的代码,还是易读但效率稍差的代码?
问题背景
给定字符串数组words,返回仅能用美式键盘同一行字母输入的单词。美式键盘布局:
- 第一行:
qwertyuiop - 第二行:
asdfghjkl - 第三行:
zxcvbnm
方案一:高效但代码冗长
var findWords = function(words) { const first_row = "qwertyuiop"; const second_row = "asdfghjkl"; const third_row = "zxcvbnm"; let row = "first"; let accepted_words = []; words.forEach((word) => { for (var i = 0; i < word.length; i++) { if (i === 0) { if (first_row.includes(word[i].toLowerCase())) { if (i === word.length - 1) accepted_words.push(word); row = "first"; } else if (second_row.includes(word[i].toLowerCase())) { if (i === word.length - 1) accepted_words.push(word); row = "second"; } else if (third_row.includes(word[i].toLowerCase())) { if (i === word.length - 1) accepted_words.push(word); row = "third"; } else { break; } } else { if (first_row.includes(word[i].toLowerCase()) && row === "first") { if (i === word.length - 1) accepted_words.push(word); } else if (second_row.includes(word[i].toLowerCase()) && row === "second") { if (i === word.length - 1) accepted_words.push(word); } else if (third_row.includes(word[i].toLowerCase()) && row === "third") { if (i === word.length - 1) accepted_words.push(word); } else { break } } } }); return accepted_words; }
方案二:简洁但效率稍低
var findWords = function(words) { const rows = ["qwertyuiop", "asdfghjkl", "zxcvbnm"]; let accepted_words = []; words.forEach((word) => { for (row of rows) { for (var i = 0; i < word.length; i++) { if (row.includes(word[i].toLowerCase())) { if (i === word.length - 1) { accepted_words.push(word); } } else { break } } } }); return accepted_words; }
分析与建议
绝大多数场景下,优先选简洁易读的代码,原因如下:
- 性能差距可忽略:两种方案的实际性能差极小——最多多遍历一次键盘行(总共3行),常规输入规模下用户完全感知不到速度差异。
- 维护成本更低:简洁代码更容易理解、修改和调试。比如后续要调整键盘布局,方案二只需修改
rows数组;方案一则要改动多个if-else分支,容易出错。 - 优化空间充足:如果真遇到性能瓶颈,方案二可以轻松优化,同时保留简洁性。比如把每行字符串转成
Set,让字符查找从O(n)变成O(1),还能提前跳出循环减少冗余遍历:
var findWords = function(words) { const rows = [ new Set("qwertyuiop"), new Set("asdfghjkl"), new Set("zxcvbnm") ]; let accepted_words = []; words.forEach((word) => { for (const row of rows) { let isValid = true; for (const char of word.toLowerCase()) { if (!row.has(char)) { isValid = false; break; } } if (isValid) { accepted_words.push(word); break; // 找到符合的行就停止遍历其他行 } } }); return accepted_words; }
这个优化版本性能和方案一持平甚至更好,代码依然清晰易懂。
只有当你明确输入规模极大(比如百万级以上单词),且性能测试证明方案一的提升是必需的,才考虑用方案一。但即便如此,也一定要给方案一加详细注释,降低后续维护成本。
内容的提问来源于stack exchange,提问作者metrallador10
相关产品推荐
相关产品推荐

