剑指Offer系列之「字符流中第一个不重复的字符」

    科技2025-02-12  13

    请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。

    如果当前字符流没有存在出现一次的字符,返回#字符。

    思路: 只使用一个数组,数组中不仅可以判断是否出现了多次,并且在出现一次时,数组中存放字符在字符流中出现第一次的位置,而数组索引和字符的ASCII码对应起来,由于ASCII码有128个字符,因此数组大小为128即可。   将数组初值赋值-1,某个字符第一次出现时,将-1更新成当前字符在字符流中的索引(位置)。第二次出现时,将之前赋值的索引覆盖,并且不用进入后续的判断,这里选择赋值成-2)。也就是说,没出现过,数组记录-1,出现一次,数组记录位置,出现多次,数组记录成-2。   而在FirstAppearingOnce方法中,我们要遍历数组找到正确的解,所以我们要做两件事:

    找到所有出现1次的字符,由于要求我们返回第一次出现一次的字符;比较各个出现1次的字符在字符流中的位置,找到最先出现的那个字符即位置最小的字符。因此还需要设置一个变量,该变量记录某个字符的位置,在找到下一个出现一次的字符时,比较这两个只出现1次的字符的位置,看谁更靠前,就要谁。

    总结,这个方法只利用一个数组,就完成了记录某个字符是否出现了一次,以及出现一次时的在字符流的位置。

    import java.util.*; public class Solution { private int index = 0; private static int[] arr = new int[128]; static{ Arrays.fill(arr,-1); } //Insert one char from stringStream public void Insert(char ch){ if(arr[ch] == -1){ arr[ch] = index; }else if(arr[ch]>=0){ arr[ch] = -2; } index++; } //return the first appearance once char in current stringStream public char FirstAppearingOnce(){ int minIndex = Integer.MAX_VALUE; char res = '#'; for(int i=0; i<128; i++){ if(arr[i]>=0 && arr[i] < minIndex){ res = (char)i; minIndex = arr[i]; } } return res; } }

    时间复杂度:O(N) 空间复杂度:O(N)

    Processed: 0.014, SQL: 8