面試題35:第一個只出現一次的字符


題目:在字符串中找出第一個只出現一次的字符。如輸入“abaccdeff”,則輸出‘b’。

方法1:

看到這個題目,最直觀的想法就是就是遍歷法,也就是從頭開始取字符串中的一個字符,將其與其后的所有字符比較,如果有相同的字符,那么就證明它不是只出現一次的字符。當第一次出現遍歷完其后字符並且沒有重復時,表明這個字符就是“第一個只出現一次的字符”。如果字符串有n個字符,每個字符可能與后面的O(n)個字符相比較,因此這種思路的時間復雜度是O(n2)。

方法2:

題目中要求第一個只出現一次的字符,那么就跟字符出現的次數有關。我們考慮如何統計字符出現的次數,然后找出第一個次數為1的那個字符。這里我們需要一個數據容器來保存字符出現次數,並且能夠通過字符找出其相對應的次數。哈希表就是一種常用用的容器。

我們可以定義哈希表的鍵值(Key)是字符的ASCII值,而值(Value)是該字符出現的次數。同時我們需要掃描兩次字符串,第一次掃描字符串時,每掃描到一個字符就在哈希表的對應項中把次數加1。接下來第二次掃描的時候,沒掃描到一個字符就能在哈希表中得到該字符出現的次數。找出第一個Value為1的那個key就是我們需要找到那個字符。

方法1和方法2的代碼實現

View Code
#include<iostream>
#include<stdlib.h>
using namespace std;

//O(n^n)的時間復雜度
char FirstNotRepeatingChar2(char *pString)
{
    //如果是空指針,返回\0
    if(pString==NULL)
        return '\0';

    int len=strlen(pString);
    for(int i=0;i<len;i++)
    {
        int flag=0;//標識位,0表示這個字符只出現一次。
        for(int j=i+1;j<len;j++)
        {
            if(pString[i]==pString[j])
            {
                flag=1;//1表示在當前字符后面存在於該字符相同的字符。
            }
        }

        if(flag==0)
            return pString[i];
    }
    return '\0';
}

//O(n)的時間復雜度
char FirstNotRepeatingChar(char *pString)
{
    //如果是空指針,返回\0
    if(pString==NULL)
        return '\0';
    //定義hash表長度256,並創建哈希表
    const int len=256;
    int hashtable[len];

    for(int i=0;i<len;i++)
    {
        hashtable[i]=0;
    }

    char *pHashkey=pString;
    //第一遍遍歷字符串,求出每個字符出現的次數
    while((*pHashkey)!='\0')
    {
        hashtable[*(pHashkey++)]++;
    }

    pHashkey=pString;
    //第二遍遍歷字符串,求出第一個只出現一次的字符,每次都是按照字符串的順序遍歷
    while((*pHashkey)!='\0')
    {
        if(hashtable[*pHashkey]==1)
            return *pHashkey;
        pHashkey++;
    }
    return '\0';
}

void main()
{
    char *pString="abaccdeff";
    //cout<<pString<<endl;
    //cout<<pString[1]<<endl;
    cout<<sizeof(pString)<<endl;//4
    cout<<strlen(pString)<<endl;//9
    cout<<FirstNotRepeatingChar(pString)<<endl;
    cout<<FirstNotRepeatingChar2(pString)<<endl;
    system("pause");
}

字符(char)是一個長度為8bit的數據類型,因此總共最多能夠表示256種字符。所以在前面的代碼示例中我們直接創建了一個長度為256的整型數組,每個字符根據其ASCII值作為數組的下標對應數組的一個數字,而數組中存儲的是每個字符出現的次數。這樣我們就創建了一個大小為256,以字符ASCII嗎為鍵值的哈希表。

但是假如我們的字符串長度小於256,那么我們可以通過創建一個字符串長度的整型數組來存放鍵值,鍵值是ASCII%len。代碼實現如下:

View Code
char FirstNotRepeatingChar3(char *pString)
{
    //如果是空指針,返回\0
    if(pString==NULL)
        return '\0';

    int len=strlen(pString);//求字符串長度
    int *hashtable=new int[len];//定義一個動態數組,其長度為字符串的長度
    //初始化動態數組,初始值為0
    for(int i=0;i<len;i++)
    {
        hashtable[i]=0;
    }
    char *pHashkey=pString;
    //第一遍遍歷字符串,求出每個字符出現的次數
    while((*pHashkey)!='\0')
    {
        hashtable[(*(pHashkey++))%len]++;
    }

    pHashkey=pString;
    //第二遍遍歷字符串,求出第一個只出現一次的字符,每次都是按照字符串的順序遍歷
    while((*pHashkey)!='\0')
    {
        if(hashtable[(*pHashkey)%len]==1)
            return *pHashkey;
        pHashkey++;
    }
    return '\0';
}

上述思想錯誤,因為ASCII%len結果相等,但是ASCII可能不相等。比如字符串為“abacdeffk”,那么第一個只出現一次的字符不是b,而是c。這是因為b跟k對len求hash值結果相同。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM