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();
    }




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