1. 程式人生 > >LeetCode 題3 無重複字元的最長子串

LeetCode 題3 無重複字元的最長子串

刷LeetCode時遇到的一道覺得稍微有點難度的題,記錄一下

給定一個字串,找出不含有重複字元的最長子串的長度。

示例 1:

輸入: "abcabcbb"
輸出: 3 
解釋: 無重複字元的最長子串是 "abc",其長度為 3。

示例 2:

輸入: "bbbbb"
輸出: 1
解釋: 無重複字元的最長子串是 "b",其長度為 1。

示例 3:

輸入: "pwwkew"
輸出: 3
解釋: 無重複字元的最長子串是 "wke",其長度為 3。
     請注意,答案必須是一個子串"pwke" 是一個子序列 而不是子串。

本題的主要思路如下:

最簡單的思路肯定是先從頭開始遍歷,迴圈到第N個字元,在第N個字元之前的字串中遍歷,看是否存在N,若不存在,則N+1繼續,若存在,記住目前的子串長度,從下一個字元開始繼續遍歷。這種最壞的情況下是要遍歷(n+1)*n/2 次。

轉換思路,在遍歷的過程中,可以把之前的字串中存在的字元存在一個Map中,這樣確認下一個字元是否在之前的串中就只需要在Map中查詢,Map的key為字元,value為該字元在全字串中的索引。

定義幾個變數,其中iPosition是用來記錄目前的子串是從哪裡開始。比如abcaef,iPosition一開始為0,當遍歷到i ==3時,a出現了重複,這時候iPosition應該加1變為1。

如abcbef,iPosition一開始為0,當遍歷到i ==3時,abcb出現了重複,可以發現iPosition加1的話,從b開始遍歷,到了bcb又出現了重複,且子串的長度還小於abcb。可以發現iPosition的正確位置應變為重複的字元所在map中的vaule+1(這也是為什麼Map中存的value為索引的原因)。

在while迴圈中開始遍歷字串,若字串中的字元不在Map中,說明目前沒有重複,i++,且該字元加入Map中。若出現重複,先計運算元串長度,然後把老iPosition到新iPosition之間的字元,從Map中刪除(因為要從新iPostion之後開始計算了)。最後把Map中字元對應的value替換成最新的。

while迴圈的結束條件:

1.字串中剩下的子串長度已經小於目前的result

2.字串結束。

迴圈中的if判斷若為真是不會重新整理Result的,所以迴圈結束後要重新整理一次。比較一下目前的Result和最後得到的子長度,取大者即為結果。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        map<char,int> mcharint;
        int result = 0;
        int iPosition = 0;
        int i = 0;
        int size = s.size();
        while(size-iPosition > result && s[i] !=NULL)
        {
            auto iter = mcharint.find(s[i]);
            //Not find it
            if(iter == mcharint.end())
            {
               mcharint[s[i]] = i;
            }
            //Find it 
            else
            {
                result = (i - iPosition)>result?(i - iPosition):result;
                for(int j = iPosition;j<iter->second + 1;j++)
                {
                    mcharint.erase(s[j]);
                }
                iPosition = iter->second + 1;              
                mcharint[s[i]] = i;
            }
            i++;
        }
        result = (i-iPosition)>result?(i-iPosition):result;
        return result;
        
    }
};