查找字符串中首个不重复字符:两种高效方法详解
2025-01-03 01:41:34
寻找字符串中首个不重复字符
编程中,经常遇到需要在字符串中寻找特定字符的情况。一个常见的挑战是:给定一个字符串,找出其中第一个不重复出现的字符。这类问题看起来简单,但解决它需要仔细考虑各种效率问题。
方法一:利用哈希表计数
一个直接的方案是使用哈希表(在 JavaScript 中表现为普通对象或 Map)来记录每个字符出现的次数。遍历一遍字符串,将每个字符的出现次数存储在哈希表中。完成计数后,再次遍历字符串,检查每个字符的计数是否为1,若是,则该字符为首个不重复的字符。
此方法的关键在于用哈希表快速统计字符频率,避免重复计算,实现了较优的时间效率。
实现步骤
- 创建一个空对象,用于存储字符计数。
- 遍历输入字符串。对于每个字符,检查对象中是否已存在对应键,若存在则计数加一,否则将该键初始化为1。
- 再次遍历输入字符串。查找对象中值等于1的键对应的字符,找到后直接返回该字符。
- 如果完成遍历,未找到不重复的字符,返回 null 或一个指定的默认值。
代码示例
function findFirstNonRepeatingChar(str) {
const charCounts = {};
for (const char of str) {
charCounts[char] = (charCounts[char] || 0) + 1;
}
for (const char of str) {
if(charCounts[char] === 1) {
return char;
}
}
return null;
}
// 使用示例
const testString1 = 'aba';
const result1 = findFirstNonRepeatingChar(testString1);
console.log(`字符串 "${testString1}" 的第一个不重复字符是: ${result1}`); // 输出: b
const testString2 = 'aabcbd';
const result2 = findFirstNonRepeatingChar(testString2);
console.log(`字符串 "${testString2}" 的第一个不重复字符是: ${result2}`); // 输出: c
const testString3 = 'aabbcc';
const result3 = findFirstNonRepeatingChar(testString3);
console.log(`字符串 "${testString3}" 的第一个不重复字符是: ${result3}`); // 输出: null
代码解析
代码首先创建charCounts
对象来记录每个字符出现的次数。随后,代码进行两次遍历,第一次遍历计算字符频率,第二次遍历检查并返回首个出现一次的字符。如找不到,返回 null
。此方法简单有效。
方法二:利用 indexOf
和 lastIndexOf
也可以使用 JavaScript 字符串对象的内置方法 indexOf
和 lastIndexOf
。如果一个字符在这两个方法返回的索引相同,则意味着该字符仅出现一次。该方法的好处是不需要额外的数据结构,如哈希表,但可能带来较高的复杂度。
实现步骤
- 遍历字符串。
- 对于每个字符,使用
indexOf
查找字符首次出现的索引,使用lastIndexOf
查找字符最后一次出现的索引。 - 若两个索引相等,返回当前字符。
- 完成遍历后仍未找到则返回 null或一个默认值。
代码示例
function findFirstNonRepeatingChar_indexOf(str) {
for(let i = 0; i < str.length; i++){
const char = str[i];
if(str.indexOf(char) === str.lastIndexOf(char)){
return char
}
}
return null
}
// 使用示例
const testString1_index = 'aba';
const result1_index = findFirstNonRepeatingChar_indexOf(testString1_index);
console.log(`字符串 "${testString1_index}" 的第一个不重复字符是: ${result1_index}`);
const testString2_index = 'aabcbd';
const result2_index = findFirstNonRepeatingChar_indexOf(testString2_index);
console.log(`字符串 "${testString2_index}" 的第一个不重复字符是: ${result2_index}`);
const testString3_index = 'aabbcc';
const result3_index = findFirstNonRepeatingChar_indexOf(testString3_index);
console.log(`字符串 "${testString3_index}" 的第一个不重复字符是: ${result3_index}`);
代码解析
这段代码直接遍历字符串。 对每一个字符,调用 indexOf
和 lastIndexOf
来查找第一次出现和最后一次出现的位置,如果索引相等就返回该字符,找不到则返回 null
。 简洁易懂,依赖于字符串内建方法。
选择策略
通常情况下,第一种方法——哈希表计数——拥有更好的时间效率。因为它只需要两次 O(n) 的遍历(其中 n 是字符串的长度),整体的时间复杂度是O(n)。第二种方法 indexOf
和 lastIndexOf
方法本身的时间复杂度通常为 O(n), 而我们在循环内部执行这两个方法, 会产生 O(n^2) 级别的时间复杂度,更适用于字符串比较短,对效率要求不高的场景。 选择哪种方法需要权衡执行效率和代码简洁性。
无论选择哪种方法,在实际应用中都应根据具体的使用场景来选择最合适的方案。 对一些特殊情况,例如超长的字符串或者字符集非常大的情况,也要留意可能引发的问题。 优先保证代码运行的正确性,而后可以考虑代码的优化方向。