1. 程式人生 > 其它 >雜湊表--面試題50-I、-II

雜湊表--面試題50-I、-II

技術標籤:劍指offer

文章目錄

面試題50-I 第一個只出現一次的字元

在字串 s 中找出第一個只出現一次字元。如果沒有,返回一個單空格。

示例:

s = "abaccdeff"
返回 "b"

s = "" 
返回 " "

題解:

模式識別:涉及次數要考慮用雜湊表,一般字元為key,下標為值(或依據題意為其它)。

具體步驟:
在這裡插入圖片描述
程式碼:

class Solution {
public:
    char firstUniqChar
(string s) { map<char,int> hashmap; for(char val:s){ if(hashmap.find(val)==hashmap.end()) hashmap[val]=1; else hashmap[val]++; } for(char val:s){ if(hashmap[val]==1) return val; } return ' '; } };

在這裡插入圖片描述
時間複雜度 O(N)

空間複雜度 O(1)

面試題50-II 字元流中第一個不重複的字元

題目:
請實現一個函式用來找出字元流中第一個只出現一次的字元。例如,當從字元流中只讀出前兩個字元"go"時,第一個只出現一次的字元是"g"。當從該字元流中讀出前六個字元“google"時,第一個只出現一次的字元是"l"。

返回值描述:
如果當前字元流沒有存在出現一次的字元,返回#字元。

題解(雜湊+佇列):
題解:
具體參考這:參考

針對題目的描述,我們先提出兩個問題?

Q1. 給定一個字串(只不過這裡的字串是可變的),如果快速判斷一個字元是否存在於字串中,如果存在,也就是重複?

Q2. 這裡先不考慮重複,如果快速返回第一個字元?有沒有感覺有點像先來先服務?

對於一道題,如果沒有思路,就要針對題目給自己問問題。然後針對問題,來考慮需要什麼樣的演算法或者資料結構。

A1:對於“重複問題”,慣性思維應該想到雜湊或者set。對於“字串問題”,大多會用到雜湊。因此一結合,應該可以想到,判斷一個字元是否重複,可以選擇用雜湊,在c++中,可以選擇用unordered_map<char, int>

A2:對於字元流,源源不斷的往池子中新增字元,然後還要返回第一個滿足什麼條件的字元,顯然設計到了“順序”,也就是先來的先服務,這種先進先出的資料結構不就是佇列嘛。因此,這裡可以用佇列。

假如你已經知道了要用hash 和 queue 這兩個資料結構,你可以試著自己想一想,接下來的演算法過程是怎麼樣的?
這裡我提供一個演算法過程,如下:

1、初始化一個unordered_map<char, int> mp, queue q

2、對於Insert(char ch)操作, 如果ch是第一次出現,則新增到q中,然後在mp中記錄一下次數,如果不是第一次出現,也就是重複了,那麼我們就沒必要新增到q中,但是還是需要在mp中更新一下次數,因為之後要根據次數來判斷是否重複。

3、對於FirstAppearingOnce()操作,我們直接判斷q的頭部,然後在mp中檢查一下,是否重複,如果沒有重複,那就是我們想要的資料。否則,如果重複了,那就應該彈出頭部,然後判斷下一個頭部是否滿足要求。
因為佇列中儲存的 “不重複字元” 在一系列的流讀取操作後,隨時有可能改變狀態(變重複),所以,佇列中的字元不能直接輸出,要先進行一次重複判斷,如果發現隊頭字元已經重複了,就將它移出佇列並判斷新的隊頭,否則,輸出隊頭的值;
程式碼:

class Solution
{
public:
    map<char, int> hashmap;
    queue<int> q;
  //Insert one char from stringstream
    void Insert(char ch)//字元流肯定是要一個一個的輸入的,所以要有Insert()操作;
    {
        if(hashmap.find(ch)==hashmap.end()) q.push(ch);
        hashmap[ch]++;
    }
  //return the first appearence once char in current stringstream
    char FirstAppearingOnce()
    {
        while(!q.empty()){
            char ch=q.front();
            if(hashmap[ch]==1) return ch;
            else q.pop();
        }
        return '#';
    }

};

時間複雜度O(N):對於Insert(char ch)操作,為O(1), 對於FirstAppearingOnce()操作,為O(N),因為最壞情況下,佇列中存入一半的重複資料, 比如“abcdabcd”,佇列會存入“abcd”,並且彈出的時候都是重複的。

空間複雜度:O(N),建立了雜湊表和佇列