第一次只出现一个的字符(哈希)

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

最直观的想法就是遍历字符串,每遇到一个字符都遍历后面的字符,看有没有不重复的,这种做法最好是O(n),平均是O(n2),所以并不是最好的。
那第二种方法就是统计每个字符在字符串中出现的位置,那要有一个东西来记录就是用空间换时间,比如哈希表。
哈希表可以把一个字符映射成一个数字,所以哈希表的key定义为字符,value定义为数字,就可以遍历一遍得到每个字符的出现次数,然后再遍历一遍,出现一次的第一个字符就是第一个。hashmap可以直接拿来用,但这个题可以通过自己实现一个简单的哈希表。
哈希的原理就是把散列,将任意长度的输入压缩成一个固定长度的输出。性质是不同输入可能有相同输出,但每次输入后输出的结果要不变,若输入很多,则输出要均匀分布到输出域中。hashmap的实现就是将键经过hash之后得到一个固定长度的散列值,再模表的长度得到一个值,将键和值挂在这个值后面,如果有别的键也得到这个值,就挂在第一个值后面。
如果要自己实现一个哈希表,char有8位,所以共有种256可能,所以此时就以此时这个字符的ascii码作为key,其中存的值作为value表示键出现的个数。这个数组的大小为一个常数,所以空间复杂度可以算作O(1),总的时间复杂度为O(n)。

public class Solution {
    public int FirstNotRepeatingChar(String str) {
        int[] val=new int[256];
        for(int i=0;i<str.length();i++){
            val[str.charAt(i)]++;            
        }
        for(int i=0;i<str.length();i++){
            if(val[str.charAt(i)]==1)return i;
        }
        return -1;
    }
}

如果此时不是要求字符而是汉字,那就不可以用一个256长度的数组了

因为汉字是两个字符,所以就是16位,弄一个2^16次的数组。6万多
也可以用标准的汉字编码,比如GBK,有21003个汉字编码,还不如直接用hashmap

定义函数,两个字符串为参数,要从第一个字符串中删除第二个字符串中出现的所有字符

所以这时就可以将第二个字符串存储到一个哈希表(简单)中,再遍历第一个字符串,如果发现有就删除。O(n)

定义函数,删除所有重复出现的字符

先遍历一遍,存到一个布尔型哈希表中,再遍历一遍,删除原有的字符,O(n)

判断字符串是否是变位词

变位词就是字母相同,出现次数也相同的字符串,这时就可以用一个哈希表遍历第一个,然后记录字母和出现次数,再遍历第二个,遇到就减去,如果哈希表值都是0则为变位词

找到字符流中第一次只出现一次的字符

是一个实时的,也就是随着字符的输入,这个值应该是不断变换的。
所以每输入一个字符就往哈希表中存一个值,如果这个值为-1,则是第一个存入,就把它变成此时这个值在字符中出现的位置,如果第二次出现就变成-2,这样的话,每个值都是记录的他出现的顺序,找到大于0且最小的值,就是该输出的字符。
记得初始化数组在构造函数中,不能在外面初始化。外面只能定义。

public class Solution {
    //Insert one char from stringstream
    static int[] arr=new int[256];
    int num=-1;
   
    public Solution(){
        for(int i=0;i<256;i++){
            arr[i]=-1;
        }
    }
    public void Insert(char ch)
    {
        if(arr[ch]==-1){
            arr[ch]=++num;
            return;
        }
        if(arr[ch]!=-1 && arr[ch]>=0){
            arr[ch]=-2;
        }
    }
  //return the first appearence once char in current stringstream
    public char FirstAppearingOnce()
    {    int index=-1;
         int  seq=Integer.MAX_VALUE;
        for(int j=0;j<256;j++){
            if(arr[j]>=0 && arr[j]<seq){
                seq=arr[j];
                index=j;
            }
        }
        if(seq!=Integer.MAX_VALUE){
            return (char)index;
        }else{
            return '#';
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值