#CodeLog 03 第一个只出现一次的字符

本文介绍了一种利用ASCII码和哈希表高效查找字符串中首次出现的唯一字符的方法,通过定义一个58长度的数组来存储各字母出现次数,实现O(n)时间复杂度的查找。

题目:
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).

分析:
其实主要还是hash,利用每个字母的ASCII码作hash来作为数组的index。
首先,需要定义一个长度为58的数组来存储每个字母出现的次数。58的理由如下:

因为区分大小写,大写A-Z对应的ASCII码为65-90,小写的a-z对应的ASCII码值为97-122,一共26*2=52个英文字母,大写的Z和小写的a之间有91~96共6个位置的空缺,所以需要用一个58长度的数组来存储每个字母出现的次数。

而每个字母的index=int(word)-65,比如g=103-65=38,而数组中具体记录的内容是该字母出现的次数,最终遍历一遍字符串,找出第一个数组内容为1的字母就可以了,时间复杂度为O(n)

代码:

int FirstNotRepeatingChar(string str) {
        int a[58]={0};//动态生存期的元素初始化是随机的,赋初值为0
        for(int i=0;i<str.length();i++)
        {
            a[(int)str[i]-65]+=1;
        }
        for(int i=0;i<str.length();i++)
        {
            if(a[(int)str[i]-65]==1)
            {
                return i;
            }
        }
        return -1;
    }

Tips

  1. 数组的声明
    数组属于自定义数据类型,因此在使用前首先要进行类型声明。声明一个数组类型,应该包括以下几个方面。
    (1)确定数组的名称
    (2)确定数组元素的类型
    (3)确定数组的结构(包括数组维数,每一维的大小等)
    数组类型声明的一版形式为:

    数组类型 标识符【常量表达式1】【常量表达式2】

    数组中元素的类型是由"数据类型"给出,可以是整型、浮点型等基本类型,也可以是结构体、类等自定义类型。数组名称有“标识符”表示。常量表达式1指定了数组每一维的大小
    例如:int a[10];
    表示a为int型数组,有10个元素:a[0]~a[9],可以用于存放有10个元素的整数序列。

    本题通过分析可以确定数组的长度为58,类型为int,因此可以直接采用int a[58]声明数组

  2. 数组的初始化
    数组初始化就是在声明数组时给部分或全部元素赋初值。当指定的初值个数小于数组大小时,剩下的数组元素会被赋予0值。若定义数组时没有指定任何一个元素的初值,对于静态生存期(static修饰) 的数组,每个元素仍然会被赋予0值;但对于 动态生存期(幽冥局部生存期对象,其诞生于声明点,结束于声明所在块执行完毕之时)的数组,每个元素的初值都是不确定的。

    本题中声明的数组用于记录每个字符在字符串中出现的次数,因此应设初值为0值,且声明的数组属于动态生存期的数组,因此应在声明的同时进行初始化,即int a[58]={0};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值