• 剑指offer35题:第一个只出现一次的字符+剑指offer55题:字符流中第一个不重复的字符+剑指offer51题:数组中重复的数字


      在看剑指offer的时候,感觉这三个题目很像,都是用哈希表可以解决,所以把这三个题整理出来,以供复习。

      剑指offer35题:第一个只出现一次的字符

      题目描述:在字符串中找出第一个只出现一次的字符。如输入“abaccdeff”,则输出‘b’.

      题目分析:统计字符串每个字符出现的次数,然后找出第一个只出现一次的字符。我们可以定义一个哈希表,这个哈希表的键值key是字符,value是该字符出现的次数。这样我们需要对字符串扫描两次,第一次扫描字符串时,每扫描一个字符就在哈希表对应项中把次数加1.第二次扫描时,每扫描一个字符就能从该哈希表中该字符出现的次数。这样没扫描一遍时间复杂度为O(n),扫描两次的总时间复杂度仍为O(n).由于数组大小为常数,所以空间复杂度为O(1).

      代码如下:

    #include<iostream>
    using namespace std;
    char FirstNotReaptingchar(char* pString)
    {
        if (pString == NULL)
            return '';
        const int tablesize = 256;                   //总共有256个字符
        unsigned int hashtable[tablesize];
        for (unsigned int i = 0; i < tablesize; ++i)      //初始化
        {
            hashtable[i] = 0;
        }

        char* hashKey = pString;
        while (*hashKey != '')                  //第一次扫描字符串,统计相应字符出现的次数
        {
            hashtable[*(hashKey++)]++;
        }
        hashKey = pString;
        while (*hashKey != '')       //第二次扫描字符串,得出相应字符出现的次数并判断
        {
            if (hashtable[*hashKey] == 1)
                return *hashKey;
                hashKey++;
        }
        return '';
    }
    void main()
    {
        char ch = FirstNotReaptingchar("abaccdeff");
        printf("%c ", ch);
    }

      剑指offer55题:字符流中第一个不重复的字符

      题目描述:请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当字符流中只读出前两个字符“go”时,第一个只出现一次的字符是‘g’。当从该字符流中读出前六个字符“google”时,第一个只出现一次的字符是‘l’.

      分析:我们可以看到这个题跟上面的题很像,因此可以用同样的数据结构哈希表来解决这个问题。由于字符只有256个,我们可以定义一个长度为256的哈希表。

      #include<iostream>
    using namespace std;
    class solution
    {
    public:
        solution()
            :index(0)
        {
            for (int i = 0; i < 256; ++i)
                hashtable[i] = -1;
        }

        void Insert(char ch)
        {
            if (hashtable[ch] == -1)                          //如果hashtable[ch]==-1,表示没有这个字符
                hashtable[ch] = index;         //如果hashtable[ch]==-2,表示这个字符出现多次
             else if (hashtable[ch] >= 0)                    //如果hashtable[ch]>=0,表示这个字符只出现过一次
                hashtable[ch] = -2;
            index++;
        }
        
        char FirstapearringOnce()
        {
            char ch = '';
            int minIndex = numeric_limits<int>::max();   //标准模板库里面,表示取整型的最大值。
            for (int i = 0; i < 256; ++i)
            {
                if (hashtable[i]>=0 && hashtable[i] < minIndex)
                {
                    ch = (char)i;
                    minIndex = hashtable[i];
                }
            }
            return ch;
        }
    private:
        int index;
        int hashtable[256];
    };
    void main()
    {
        solution s;
        s.Insert('g');
        s.Insert('o');
        /*s.Insert('o');
        s.Insert('g');
        s.Insert('l');
        s.Insert('e');*/
        char ch=s.FirstapearringOnce();
        printf("%c ", ch);
    }

      剑指offer51题:数组中重复的数字

      题目描述:在一个长度为n的数组里面的所有的数字都在0到n-1的范围内。数组中某些数字是重复的,但是不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输出长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3.

      分析:这道题一看,就可以通过哈希表统计出每个数字出现的次数,然后找出次数大于1的数字。但是这里有个问题是,哈希表要开辟多大呢?我们知道哈希表是静态的,当输入的数据个数与哈希表大小不匹配时,是无法解决的。所以我们可以考虑书上提供的思路。以数组{2,3,1,0,2,5}为例,数组的第0个数字是2(从零开始计数,和数组的下标保持一致),与他的下标不等,于是把他与下标为2的数字交换,交换后的数组是{1,3,2,0,2,5,3}...依次类推得到数组{0,1,2,3,2,5,3}。我们可以看到下标为1,2,3的三个数字分别为1,2,3,他们的下表和数值都相等,因此不需要做任何操作。接下来扫描到下标为4的数字2.由于他的数值和下标不相等,所以比较他和下标为2的数字。此时下标为2的数字也是2,也就是说,下标为2和下标为4的两个位置都出现了,因此找到一个重复的数字。

      代码:

    #include<iostream>
    using namespace std;
    bool FindReaptNum(int* a,int n,int* value)
    {
        if (a == NULL || n < 0)
            return false;
        for (int i = 0; i < n; ++i)
        {
            if (a[i]<0 || a[i]>n - 1)
                return false;
        }
        const int tablesize = n;
        for (int i = 0; i < n; ++i)
        {
            while (a[i] != i)
            {
                if (a[i] = a[a[i]])
                {
                    *value = a[i];
                    return true;
                }
                    

                int tmp = a[i];
                a[i] = a[tmp];
                a[tmp] = tmp;
            }
        }
        return false;
    }
    void main()
    {
        int a[] = { 2, 3, 1, 0, 2, 5, 3 };
        int* value=NULL;
        int num=FindReaptNum(a, sizeof(a)-1,value);
        printf("%d ",num);
    }

      总结:综上三个题目,我们可以了解到,使用哈希表解决问题时,应统计字符的出现次数,而统计整数数组时是不可以的,必须重新找其他思路。

  • 相关阅读:
    要发布游戏啦,平台要 3000个6位不重复的验证码 看我怎么做!!!
    数字化婚姻配对尝试
    java 和 .NET 的 类继承方面 的不同
    Asp.Net Core 实现谷歌翻译ApI 免费版
    Asp.Net Core 全局模型验证
    Asp.Net Core 下 Newtonsoft.Json 转换字符串 null 替换成string.Empty
    Windows 10 远程连接出现函数错误 【这可能由于CredSSP加密Oracle修正】
    矫正系统时间
    linux 安装WildFly 及可能遇到的问题
    ubuntu 安装 jdk-7
  • 原文地址:https://www.cnblogs.com/qingjiaowoxiaoxioashou/p/6414002.html
Copyright © 2020-2023  润新知