【字符串】无重复最长子串

题目描述:给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

1、比较笨的办法,就是三层的嵌套循环,第一层遍历子串的起始位置,第二层遍历子串的终止位置,第三层遍历起始到终止间的所有子串,这样遍历所有可能情况,找出最长子串,时间复杂度O(n^3):

int lengthOfLongestSubstring_bad_140ms(string s) {
    int maxLength = 0;
    int i,j,k;
    for(i = 0; i<s.size(); i++){
        int Length = 1;
        for(j = i+1; j<s.size() && s[i]!=s[j]; j++){
            bool flag = true;
            for(k = i+1; k<j; k++){
                if(s[k] == s[j]){
                    flag = false;
                    break;
                }
            }
            if(flag)
                Length++;
            else
                break;
        }
        if(maxLength < Length)
            maxLength = Length;
        if(j == s.size()-1)
                break;
    }
    return maxLength;
}

2、上面的方法太笨重,这里可以利用set的性质,即无重复元素,设置i,j为划窗起始和终止下标,更新原则为:初始化i=0,j=0;set中查找j位置字符,若未找到,j++;否则set删除i索引位置的字符,i++。(隐含的问题是,删除i处的字符不一定是重复的字符,需不断删除知道重复字符被删除为止)。

int lengthOfLongestSubstring_44ms(string s) 
{
    int maxLength = 0;
    int i = 0, j=0;
    set<char> hashSet;
    while(i<s.size() && j <s.size()){
        auto it = hashSet.find(s[j]);//涉及到set的查找,红黑树查找、插入与删除,虽然效率挺高但是查找算法也大概是o(logn)的,所以这个算法其实还是比较费时的
        if(it == hashSet.end())//没有找到
        {
            hashSet.insert(s[j++]);
            maxLength = maxLength < j-i ? j-i : maxLength;
        }
        else
            hashSet.erase(s[i++]);
    }
    return maxLength;
}

3、通过建立hash表,解决2中的问题,实现精确删除,更新i的位置;这里hash表的key为字符,value为该字符的下标值+1,即下一位置。

int lengthOfLongestSubstring28ms(string s)
{
    int maxLength = 0;
    map<char, int> hashMap;
    pair<map<char, int>::iterator, bool> Insert_Pair;
    for(int i = 0, j = 0; j < s.size(); j++){
        //用来判断插入是否成功,插入不成功的时候在执行查找操作
        //一个完全优化:用字符数组存储,实现o(1)查找
        Insert_Pair = hashMap.insert(pair<char, int>(s[j], j+1));
        if(!Insert_Pair.second){
            auto it = hashMap.find(s[j]);
            //i为多个重复数据中最大下标
            i = i > it->second? i : it->second;
            //需要更新最大下标的重复元素覆盖原来的元素
            hashMap[s[j]] = j+1;
        }
        maxLength = maxLength < (j-i+1) ? (j-i+1) : maxLength;   
    }
    return maxLength;
}

猜你喜欢

转载自blog.csdn.net/qq_34606546/article/details/87626641