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

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

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

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

  1. 找到所有出现1次的字符,由于要求我们返回第一次出现一次的字符;
  2. 比较各个出现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)

猜你喜欢

转载自blog.csdn.net/weixin_44471490/article/details/108957215