P387字符串中的第一个唯一字符

这篇博客探讨了两种解决寻找字符串中第一个不重复字符的方法。第一种利用字符数组记录字符出现的位置,第二种利用队列实现延迟删除。通过遍历字符串并更新对应字符的状态,最终找到第一个不重复的字符的索引。代码示例展示了这两种高效的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

题目

  1. 字符串中的第一个唯一字符
    给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1 。

示例 1:

输入: s = “leetcode”
输出: 0
示例 2:

输入: s = “loveleetcode”
输出: 2
示例 3:

输入: s = “aabb”
输出: -1

解法一:使用字符数组存储字符索引
因为题目全是小写字母,这里就可以使用26范围大小的数组来完成字典映射,比如字符a,对应的数组位置为’a’-‘a’ = 0, 数组位置记录原始字符串数字字符出现的首次位置,遍历一次字符串即可确定每个数组索引记录的位置。代码如下:

public int firstUniqChar(String s) {

        int[] letters = new int[26];
        Arrays.fill(letters, -1);

        for (int i = 0; i < s.length(); i++) {
            if (letters[s.charAt(i) - 'a'] == -1) {
                letters[s.charAt(i) - 'a'] = i;
            } else {
                letters[s.charAt(i) - 'a'] = -2; // 重复了
            }
        }

        for (int i = 0; i < s.length(); i++) {
            if (letters[s.charAt(i) - 'a'] != -2) {
                return i;
            }
        }


        return -1;

    }

方法2: 使用队列的方式,借助队列先进先出的能力来发现首个不重复的字符串。这里用到了延迟删除的一项能力,即针对某个字符,如果它重复了的话,只要它到对列头部范围内的字符有不重复的就不会直接删除,而是它前面的全部重复了才会删除。举个例子假设队列为
c -> b -> a ->d 当前字符是c,c重复了,但是队列头部d不重复,那么这时候就不删除c,直至下次迭代新的字符时,发现d重复了,才会删除d更新新的不重复的队列头。代码如下:

public int firstUniqChar3(String s) {

        int[] letters = new int[26];
        Arrays.fill(letters, -1);

        Deque<Integer> queue = new ArrayDeque<>();
        for (int i = 0; i < s.length(); i++) {
            if (letters[s.charAt(i) - 'a'] == -1) {
                letters[s.charAt(i) - 'a'] = i;
                // 存储的是索引位置
                queue.addLast(i);
            } else {
                letters[s.charAt(i) - 'a'] = -2; // 重复了
                // 延迟删除
                while (!queue.isEmpty() && letters[s.charAt(queue.peek())-'a'] == -2) {
                 queue.pop();
                }
            }
        }


        return !queue.isEmpty() ? queue.pop() : -1;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值