【算法剖析】求字符串中無重復字符的最長字串


1、問題描述

  這個問題來自leetcode中的Longest Substring Without Repeating Characters,誠如標題所述,我們需要尋找的是在一個字符串中,沒有重復字符的最長字串。我們假定字符串中的字符只由$a$~$z$這26個字符構成。例如,對於字符串"$abcabcbb$",它的無重復字符最長字串是"$abc$",長度為3;對於字符串"$bbbb$",它的無重復最長字串是$b$,長度為1。

2、算法一

  我們能夠立即想到的,最原始的算法就是,從字符串的每一個位置開始構造字串,並逐漸增大字串長度,直到碰到一個已經出現在這個字串中的字符為止,這樣對於長度為$n$的字符串而言,經過$n$次遍歷即可求得最長的無重復字符字串。實際上,考慮到構成字符串的字母表大小只有26,每次遍歷最多也只需進行26次增長子串的操作,這個算法的整個時間復雜度為$O(26n)$。這個算法很簡單也很好理解,不再給出詳細代碼。

3、算法二

  算法二能夠將時間復雜度縮小到$O(n)$,即只遍歷一遍字符串即可。它主要基於一個思想:當我們在構建子串的時候,如果遇到了一個重復字符,那么我們可以使遍歷跳躍一定“距離”,直接忽略掉不必要的搜索。對於一個字符串$A=a_{0}a_{1}a_{2}a_{3}...a_{n-1}$,我們正在構造的字串是$B=a_ja_{j+1}...a_k$,接下來一個字符是$a_{k+1}$,但是它與當前$B$中的某一字符$a_{k'}$相同。那么對於那些所有以$a_i$,$(j+1 \le i < k)$開頭的無重復字符最長字串的長度一定小於$B$的長度。例如,對於字符串$A=$"$abcdcef$",$B=$"$abcd$",當前長度為4,下一個字符是$c$,而它與$b_3$相同,那么在$A$中,以$a_1,a_2,a_3$開頭的無重復字符最長字串,相對於$B$,“更早地”遇到了重復字符$c$,它們的長度都要小於$B$的長度。

  為了實現算法二,我們需要額外使用一個大小為26的數組$pos$以及一個變量$basePos$,$pos$用來記錄當前情況下,每個字符最近出現的那個位置,而$basePos$用來記錄所增長的子串的開始位置。初始情況下,$basePos=0$,表示第一個所增長的那個子串開始於位置0,$pos$中的每個元素都初始為-1。對於當前的字串,我們如何判斷下一個字符是否已經出現在了當前字串中呢?例如,對於字符$a$,我們檢查$pos[0] \le basePos$是否成立,成立的話,則說明$a$已經出現在當前字串中,弄明白需要搞清楚$pos$與$basePos$的含義。

  我們使用一個例子來說明這個過程。


 

初始情況

Step:1

Step:2

Step:3

Step:4

Step:5

注意,這里是由於pos['c'-'a']=2>basePos,也就是第二個c與前面的c重復了。

Step:6

Step:7


 

下面我們給出代碼,我們需要處理某些特殊情況,例如輸入字符串為空串等等。

    int lengthOfLongestSubstring(string s) {
        int pos[26];
        int i;
        
        for(i=0;i<26;i++)
        {
            pos[i]=-1;
        }
        int basePos=0;
        int maxLength=-1;
        for(i=0;i<s.length();i++)
        {
            if(pos[s[i]-'a']<basePos)
            {
                pos[s[i]-'a']=i;
            }
            else 
            {
                if(maxLength==-1||i-basePos>maxLength)
                    maxLength=i-basePos;
                basePos=pos[s[i]-'a']+1;
                pos[s[i]-'a']=i;
            }
        }
        if(s.length()-basePos>maxLength||maxLength==-1) maxLength=s.length()-basePos;
        return maxLength;
    }
算法二

 


免責聲明!

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



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