第一个只出现一次的字符

在字符串中找到第一个只出现一次的字符

问题

给定一个字符串,找出第一个只出现一次的字符。如果不存在,返回空字符串或 -1。

示例:

  • 输入:"abaccdeff" → 输出:"b"
  • 输入:"aabbcc" → 输出:""

解答

方法一:哈希表统计

function firstUniqChar(s) {
  // 用 Map 统计每个字符出现的次数
  const map = new Map();
  
  // 第一次遍历:统计频率
  for (const char of s) {
    map.set(char, (map.get(char) || 0) + 1);
  }
  
  // 第二次遍历:找第一个出现一次的字符
  for (const char of s) {
    if (map.get(char) === 1) {
      return char;
    }
  }
  
  return '';
}

// 测试
console.log(firstUniqChar('abaccdeff')); // 'b'
console.log(firstUniqChar('aabbcc'));    // ''
console.log(firstUniqChar('leetcode'));  // 'l'

方法二:indexOf + lastIndexOf

function firstUniqChar(s) {
  for (let i = 0; i < s.length; i++) {
    const char = s[i];
    // 如果第一次出现和最后一次出现的位置相同,说明只出现一次
    if (s.indexOf(char) === s.lastIndexOf(char)) {
      return char;
    }
  }
  return '';
}

方法三:返回索引位置

// LeetCode 版本:返回索引,不存在返回 -1
function firstUniqChar(s) {
  const map = new Map();
  
  for (const char of s) {
    map.set(char, (map.get(char) || 0) + 1);
  }
  
  for (let i = 0; i < s.length; i++) {
    if (map.get(s[i]) === 1) {
      return i;
    }
  }
  
  return -1;
}

console.log(firstUniqChar('leetcode')); // 0
console.log(firstUniqChar('loveleetcode')); // 2

方法四:用对象代替 Map

function firstUniqChar(s) {
  const count = {};
  
  // 统计频率
  for (const char of s) {
    count[char] = (count[char] || 0) + 1;
  }
  
  // 找第一个只出现一次的
  for (const char of s) {
    if (count[char] === 1) {
      return char;
    }
  }
  
  return '';
}

关键点

  • 两次遍历:第一次统计频率,第二次按顺序查找
  • 必须按原字符串顺序遍历,不能遍历 Map(Map 不保证插入顺序与查找顺序一致)
  • 时间复杂度 O(n),空间复杂度 O(1)(字符集有限,最多 26 或 256 个字符)
  • indexOf + lastIndexOf 方法简洁但时间复杂度是 O(n²)
  • Map 比普通对象更适合处理特殊字符作为键的情况