剑指Offer:34 第一个只出现一次的字符

看完题目后,我的第一反应就是应该用Hash表做,看了一眼讨论区都是用的Hash表,心里就有底了。

然后进一步理清了思路:

字符为key,出现次数为value,第一次遍历一遍字符串,把所有字符和对应的出现次数存入哈希表;

第二次顺序遍历字符串,对每一个字符查询出现次数,第一个次数为1的就返回。

代码如下:(这是为数不多的一次思路和代码实现都没有看书和别人的代码的)

ps:代码有漏洞,没有处理所有字符都出现不止一次的情况。

在第二次循环结束前加上:if ( i == str.size()-1 )  result=-1;

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        if (str=="") return -1;
        //将字符串遍历存入哈希表中
        std::unordered_map<char, int> map;
        //std::unordered_map<char, int>::iterator it;
        for(int i=0; i<str.size(); i++){
            if(map.find(str[i]) != map.end()){
                int temp = map[str[i]];
                map[str[i]] = ++temp;
            }
            else{
                //map(str[i]) = 1;
                map.insert(std::make_pair(str[i], 1));
            }
        }
        int result;
        for(int i=0; i<str.size(); i++){
            if(map[str[i]] == 1){
                result = i;
                break;
            }
        }
        return result;
    }
};

这道题本身花的时间并不多,写代码和debug大概一共15分钟。但是前期的大部分时间40-50分钟,都用在查STL中的String和哈希表调用方法了,这上面花费了不少时间。

C++的STL真的需要花时间好好的学一学了。

看过别人代码之后对之前代码的简化:

(可以看出之前代码写的繁琐的原因还是,对map用法的不熟悉)

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        if (str.empty()) 
            return -1;
        //将字符串遍历存入哈希表中
        std::unordered_map<char, int> map;
        //std::unordered_map<char, int>::iterator it; //可以不用map的迭代器
        for(int i=0; i<str.size(); ++i){
                //map[str[i]]  = map[str[i]]+1; //另一种写法
                ++map[str[i]];
        }
        
        int result;
        for(int i=0; i<str.size(); ++i){
            if(map[str[i]] == 1){
                result = i;
                break;
            }
            if(i == str.size()-1) result=-1;
        }
        return result;
    }
};

书上的方法:

由于只需要一个非常简单的哈希表就可以满足我们的要求,所以,可以自己用数组实现一个简单的哈希表。

代码如下:(其中对字符不需要强制类型转换成unsigned int型,可以直接用作数组的索引)

class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        if (str.empty()) 
            return -1;
        
        const int HashTableSize = 256;
        unsigned int HashTable[HashTableSize];
        for (int i=0; i<HashTableSize; ++i){
            HashTable[i] = 0;
        }
        //遍历字符串,向哈希表中对应位置存字符出现次数
        for(int i=0; i<str.size(); i++){
            ++HashTable[str[i]];
        }
        //遍历字符串,找到第一个出现次数为1的字符位置
        int posi;
        for(int i=0; i<str.size(); i++){
            if(HashTable[str[i]]==1)
            {
                posi = i;
                break;
            }
        }
        return posi;
    }
};

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值