如何用JavaScript高效查找字符串中的第一个非重复字符?
如何用JavaScript高效查找字符串中的第一个非重复字符?
兄弟,你这个问题抓得特别准!你已经意识到嵌套循环O(n²)的效率瓶颈,而且方向也找对了——用哈希表类的数据结构就能把时间复杂度降到O(n),我来给你一步步拆解实现思路和代码:
优化核心思路
我们可以把问题拆成两次线性遍历,用空间换时间:
- 第一次遍历:用哈希表(比如JS的
Map或普通对象)统计每个字符的出现次数,这一步时间复杂度O(n) - 第二次遍历:再扫一遍原字符串,去哈希表里查每个字符的计数,第一个出现次数为1的字符就是我们要找的结果,这一步也是O(n)
整体时间复杂度是O(n),空间复杂度是O(k)(k是字符串中不同字符的数量),完全解决了长字符串的性能问题。
优化后的代码实现
这里我用Map来实现(它的键值对结构天生适合统计,逻辑更直观):
function findFirstNonRepeatingChar(str) { // 第一步:统计每个字符的出现次数 const charCount = new Map(); for (const char of str) { charCount.set(char, (charCount.get(char) || 0) + 1); } // 第二步:遍历原字符串,找第一个出现次数为1的字符 for (const char of str) { if (charCount.get(char) === 1) { return char; } } // 没有找到非重复字符,返回null return null; }
如果你更习惯用普通对象(逻辑和Map完全一致,只是语法不同),也可以这么写:
function findFirstNonRepeatingChar(str) { const charCount = {}; for (const char of str) { charCount[char] = (charCount[char] || 0) + 1; } for (const char of str) { if (charCount[char] === 1) { return char; } } return null; }
代码逻辑拆解
- 统计阶段:
- 遍历字符串的每个字符,用
charCount记录出现次数:如果字符已经在表里,就把计数加1;如果是第一次遇到,就初始化为1。
- 遍历字符串的每个字符,用
- 查找阶段:
- 必须再次遍历原字符串(保证按输入顺序查找),检查每个字符的计数,第一个计数为1的直接返回——这一步是确保我们拿到的是「第一个」非重复字符,而不是哈希表中先统计到的。
- 边界处理:如果遍历完所有字符都没有找到计数为1的,返回
null。
测试验证
用你给出的例子测试:
console.log(findFirstNonRepeatingChar("swiss")); // 输出 "w" console.log(findFirstNonRepeatingChar("aabbcc")); // 输出 null
完全符合预期,而且处理10万级别的长字符串时,性能会比你原来的嵌套循环快几个数量级。
额外小提示
如果需要不区分大小写的查找(比如把"S"和"s"视为同一个字符),只需要在统计和查找时把字符统一转成小写(或大写)即可:
// 统计阶段 const lowerChar = char.toLowerCase(); charCount.set(lowerChar, (charCount.get(lowerChar) || 0) + 1); // 查找阶段 if (charCount.get(char.toLowerCase()) === 1) { return char; }
备注:内容来源于stack exchange,提问作者nikhil pachange
相关产品推荐
相关产品推荐

