剑指 Offer 50. 第一个只出现一次的字符

问题

在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。

示例:
s = “abaccdeff”
返回 “b”
s = “”
返回 " "

限制:
0 <= s 的长度 <= 50000

分析
  1. 使用哈希表(HashMap)来存储
    要求的是:字符串中,第一个只出现一次的字符
    =>对字符串进行遍历,统计其中的各个字符出现的次数,最后确认第一个只出现一次的字符,即可。
    因为统计的时候,对容器的要求:既要确定该字符是什么,又要可以记录该字符出现的次数。并且,该容器的大小是不能确定的,最大为26(因为s只包含小写字母)。
    ==>想到了用集合来进行存储。
    在集合中,list类的,与数组比较相似,不能完全满足要求;set类的也不能满足要求;=>map类的可以满足要求。
    采用hashmap来作为容器,统计该字符串中每个元素出现的次数;

(1)时间复杂度:O(n)
=>在第一次扫描时,在哈希表中更新一个字符出现的次数的时间是O(1)。如果字符串的长度为n,那么,第一次扫描的时间复杂度是O(n)。
=>第二次扫描时,同样在O(1)时间内能读出一个字符出现的次数,所以时间复杂度仍是O(n)。
==>总的时间复杂度为:O(n)
(2)空间复杂度:O(1)
使用hashmap,构建起来的辅助数组的大小是一个常数,因此可以认为这种算法的空间复杂度为O(1)

  1. 使用“有序”哈希表(LinkedHashMap)来存储
    要求的是:字符串中,第一个只出现一次的字符
    =>仍旧采用集合来存储
    ==>只不过在存储某个字符(key)的出现次数时,对它的键值的设置处比较巧妙:
    如果该字符是第一次出现,则put(item,1);
    如果该字符不是第一次出现,则修改他的键值为-1:put(item,-1);
    =>因为在第一次遍历string的时候,对于其中的字符(以key来存储)的键值的设置比较巧妙,所以第二趟遍历的时候,可以直接遍历linkedhashmap的对象(理论上可以比直接遍历string要快一点)
    采用linkedhashmap的(map接口的)entrySet():返回所有的key-value构成的集合(用Set存储):
    其中,出现的第一个:item.value != -1 的item对应的key,
    即为:string中第一个只出现一次的字符。

原理:
LinkedHashMap:可以保证在遍历Map元素时,可以按照添加的顺序实现便利------>对于频繁的遍历操作,此类执行效果高于HashMap


1)时间复杂度:O(n)
=>在第一次扫描时,在哈希表中更新一个字符出现的次数的时间是O(1)。如果字符串的长度为n,那么,第一次扫描的时间复杂度是O(n)。
=>第二次扫描时,扫描的是建立起来的LinkedHashMap的对象,理论上会比直接遍历string得到结果的时间短。
==>总的时间复杂度为:O(n)
(2)空间复杂度:O(1)
使用linkedhashmap,构建起来的辅助数组的大小是一个常数,因此可以认为这种算法的空间复杂度为O(1)

  1. 用一维数组 来实现简单的“哈希表”
    实现的思路为:
    (1)string为空 的特殊情况
    =>如果该string为空,直接return ’ ';
    (2)string中包含只出现一次的字符
    =>对string进行遍历,在遍历的过程中,对于string中的元素,将该字符对应的map[]中的值,+1;
    =>对string进行第二遍遍历,如果某个字符c对应的的map[c-‘a’] == 1,表示该字符只出现了一次,return c;
    (3)string中不包含只出现一次的字符
    =>如果该string中不包含只出现一次的字符,return ’ ';

1)时间复杂度:O(n)
=>在第一次扫描时,在哈希表中更新一个字符出现的次数的时间是O(1)。如果字符串的长度为n,那么,第一次扫描的时间复杂度是O(n)。
=>第二次扫描时,同样在O(1)的时间内能读出一个字符出现的次数。
==>总的时间复杂度为:O(n)
(2)空间复杂度:O(1)
构建起来的辅助数组的大小是一个常数26*4bit=104bit,因此可以认为这种算法的空间复杂度为O(1)

  1. 用string类的方法来求解
实现

1、使用哈希表(HashMap)来存储

class Solution {
   
    public char firstUniqChar(String s) {
   
        //定义一个hashmap,来统计字符串中各个字符出现的次数
        Map<Character,Integer> map = new HashMap<Character,Integer>();
        char resChar = ' ';//因为如果没有 只出现一次的字符,要求返回一个但空格,所以将 一个但空格设置为resChar的初始值
        
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值