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

文章描述了一种使用哈希表解决编程问题的方法,即在给定的字符串中找出第一个只出现一次的字符。通过遍历字符串,统计每个字符的频数和首次出现的位置,然后再次遍历哈希表,找出频数为1且位置信息最小的字符,返回该字符。若无这样的字符,则返回空格。

目录

题目

解题思路

题解


题目

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

示例 1:

输入:s = "abaccdeff"

输出:'b'

示例 2:

输入:s = ""

输出:' '

限制:

0 <= s 的长度 <= 50000




解题思路

如果题目是:给定一串字符,找出其中只出现一次的字符。

那么这便是非常熟悉的哈希表打法,遍历一遍字符串,统计每一个字符出现的频数,最后再遍历一遍哈希表,找出那些频度值为1的元素。

但现在题目增加了一个限制条件:第一个。

不是字母表顺序中的第一个只出现了一次的字符,而是字符串中的第一个只出现了一次的字符。

那么还是可以使用哈希表的打法来解决这道题,只不过现在哈希表还需要记录字符串中每一个字符首次出现的位置,但这也只是添加三两行代码就能解决的事情,因此并没有什么难度。

那么便可以得到一个解题的流程:

  1. 定义一个哈希表,可以使用语言自带的哈希表结构,对此不了解的或者一时想不起来的也可以使用一个二维数组来模拟哈希表(26行2列。第一列存放频数,第二列存放首次出现的位置)。
  2. 遍历字符串。
  3. 对于其中的每一个字符,由于都是小写字符,便可以将其先减去97(因为char类型和int类型是通用的,存放的都是一个数值相同的数字,只不过char中的数字对应的是ASCII码表值,其中a的ASCII码值为97)再对26取余,便可以很好地确定其在哈希表中的唯一位置。
  4. 如果对应位置上第一列的值此时为0,那么便表示该字符在字符串中还没有出现过,那么此时将其出现的频度加上1,并在对应位置的第二列记录其在字符串中的位置。
  5. 如果对应位置上第一列的值此时不为0,那么便表示该字符在字符串中已经出现过,那么此时只需要将其出现的频度加上1即可,不需要对其位置信息做任何更改。
  6. 当字符串全部遍历完毕后,再对哈希表进行一次遍历。
  7. 对哈希表中所有的出现频度为1的元素,找出其中位置信息最小的那一个元素的位置,记录其位置信息,这边将其记为pos。
  8. 如果查找了一圈后,发现没有出现频度为1的元素,那么便返回一个单空格' '。
  9. 返回pos + 97,将其重新转换为对应的字符。

那么,需不需要单独判断字符串为空时的情况呢?

可以单独判断,也可以不单独判断,因为该方法是一种通用的方法,也涵盖了空字符串的情况。




题解

class Solution {
    public char firstUniqChar(String s) {
        int[][] HashTable = new int[26][2];
        for(int i=0;i<s.length();i++){
            int HashCode = (s.charAt(i) - 97)%26;
            if(HashTable[HashCode][0] == 1){
                //如果已经出现过一次,那么便将对应位置的值置为-1
                HashTable[HashCode][0] = -1;
                HashTable[HashCode][1] = -1;
            }
            if(HashTable[HashCode][0] == 0){
                //如果还没有出现过,那么便将对应位置的值置为1
                HashTable[HashCode][0] = 1;
                HashTable[HashCode][1] = i;   //记录其出现的位置
            }
        }
        int MinPos = -1;
        int MinValue = s.length();
        for(int i=0;i<26;i++){
            if(HashTable[i][0] == 1 && HashTable[i][1] < MinValue){
                MinPos = i;
                MinValue = HashTable[i][1];
            }
        }

        if(MinPos == -1){
            return ' ';
        }else{
            return (char)(MinPos + 97);
        }
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值