【剑指offer】【字符串】48. 最长不含重复字符的子字符串

题目链接:https://leetcode-cn.com/problems/zui-chang-bu-han-zhong-fu-zi-fu-de-zi-zi-fu-chuan-lcof/

双指针算法

i在前,j在后,分别指向不重复子串的头和尾;使用一个哈希表每个字符出现的次数,当遍历到j时,发现s[j]的个数大于1,那么就让i向前移动,直到s[j]的个数等于1;
每次都判断当前的不重复子串长度是不是最大的。
时间复杂度:O(n)
空间复杂度:O(n)

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> hash;
        int res = 0;
        for(int i = 0, j = 0; j < s.size(); j++)
        {
            //如果s[j]的个数大于1,清除前面重复的s[j]
            if(++hash[s[j]] > 1)
            {
                //i往前移动,直到s[j]的个数==1
                while(i < j)
                {
                    hash[s[i]]--;
                    i++;
                    if(hash[s[j]] == 1) break;
                }
            }
            //更新res
            res = max(res, j- i + 1);
        }
        return res;
    }
};

动态规划

状态表示: f[i] 表示以i结尾的字符串的不重复子串的最大长度;
状态计算:

  1. s[i] 未出现过,f[i] = f[i - 1] + 1;
  2. s[i] 出现过,记i到s[i]上一次出现的距离为d;分两种情况:
    1). d <= f[i - 1], 那么f[i] = d;
    2). d > f[i - 1], 那么f[i] = f[i - 1] + 1;

使用一个哈希表来记录,每个字符出现的位置;初始值都为-1;代表没有出现过;

时间复杂度:O(n)
空间复杂度:O(n)

class Solution {
public:
    int lengthOfLongestSubstring(string s) {

        int curLen = 0, maxLen = 0;

        // 记录,每个字符出现的位置
        unordered_map<char, int> pos;
        for(int i = 0; i < s.length(); ++i)
            pos[s[i]] = -1;
            
        for(int i = 0; i < s.length(); ++i)
        {
            ////s[i]之前出现的位置
            int prevINdex = pos[s[i]]; 
            //s[i]之前未出现过  或者  d > f[i - 1]
            if(prevINdex < 0 || i - prevINdex > curLen)  
                ++curLen;
            // d <= f[i - 1]
            else
            {
                if(curLen > maxLen)
                    maxLen = curLen;
                curLen = i - prevINdex;
            }
            pos[s[i]] = i;
        }
        if(curLen > maxLen)
            maxLen = curLen;
        return maxLen;
           
    }
};
posted @ 2020-05-03 19:37  NaughtyCoder  阅读(99)  评论(0)    收藏  举报