3.最大無重複字符的字串

題目

https://leetcode.com/problems/longest-substring-without-repeating-characters/

查找一個字符串的子串,子串中沒有重複字符

例:

"abcabcbb" 返回 "abc"

"bbbbb返回 "b"

"pwwkew返回 "wke"

分析

 看到題目第一眼想到的是KMP算法,同樣是查找子串。

KMP是查詢固定的子串的位置,對子串可以進行預處理。 現在這算法要的是查找的子串長度不固定。所以會有所區別。

不過這算法與查找子符串算法一樣,都想在遍歷一次解決問題,目前想到的有兩種方法。

算法1, 基本算法:

從頭遍歷

對每一個字符往回遍歷查找與當前字符出現的最新一次位置。

計算子串長度

如果比歷史長度大,記錄起來

查找最引 lastIndex變量來存儲匹配的位置,以簡化代碼

int lengthOfLongestSubstring(string s) { 
        int lastMax = 0;
        int lastIndex = -1;
        for(int i = 0; i < s.length(); i++){ 
            for(int j = i-1; j > lastIndex; j--){
                if(s[i] == s[j]){
                    lastIndex =  j;
                    break;
                }
            } 
            if(i- lastIndex> lastMax){
                lastMax = i- lastIndex;
            }
        }
        return lastMax > 0 ? lastMax : s.length();
    }

與KMP算法的思路一樣,算法1有個明顯的問題就是第二個for循環,很浪費查找進度。如果第二個循環平均計算m次,那整個算法複雜訂爲 o(m*n)

對算法1的改進主要從優化第二個for循環入手,解決思路: 以空間換時間以避免不必要的計算

算法2 空間換時間

  加入緩存,存儲所有字符上一次出現的位置。 

計算長度時直接索引查找,時間複雜度爲o(1)。 

整體時間複雜度就爲o(n)

int lengthOfLongestSubstring(string s) { 
        int lastMax = 0;
        int lastIndex = -1;
        //加入緩存, 記錄字符出現的上一個位置
        int mapIndex[0x100];
        memset(mapIndex, -1, sizeof(mapIndex));
        
        for(int i = 0; i < s.length(); i++){
            if(mapIndex[s[i]] >= lastIndex){
                lastIndex = mapIndex[s[i]];
            }
            if(i- lastIndex> lastMax){
                    lastMax = i- lastIndex;
            }
             mapIndex[s[i]] = i;
            
        }
        return lastMax > 0 ? lastMax : s.length();
    }




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章