3. Longest Substring Without Repeating Characters

182 阅读2分钟

Given a string, find the length of the longest substring without repeating characters.

Example 1:

Input: "abcabcbb" Output: 3 Explanation: The answer is "abc", with the length of 3. Example 2:

Input: "bbbbb" Output: 1 Explanation: The answer is "b", with the length of 1. Example 3:

Input: "pwwkew" Output: 3 Explanation: The answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

解题过程很波折,开始的时候是没有想到很好的方法,后来想到了方法,但是思路有缺陷,卡在了abba这个测试用例上。

先来看下我的实现吧。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if (s.size() == 0) {
            return 0;
        }
        int max_len = 1;
        map<char, int> my_map = {};
        my_map[s[0]] = 0;
        for (int begin = 0, end = begin +1; end < s.size(); ){
            int num = my_map[s[end]];
            my_map[s[end]] = end;
            auto it = my_map.find(s[end]);
            if(it == my_map.end()) {
            }
            else {
                begin = num + 1;
            }
            end ++;
            max_len = max(max_len, end - begin) ;
        }
        return max_len;
    }
};

对上面的代码进行修改,可以ac的版本:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if (s.size() == 0) {
            return 0;
        }
        int max_len = 1;
        map<char, int> my_map = {};
        my_map[s[0]] = 0;
        for (int begin = 0, end = begin +1; end < s.size(); ){
            auto it = my_map.find(s[end]);
            if(it != my_map.end() && begin <= my_map[s[end]]) {
                begin = my_map[s[end]] + 1;
            }
            my_map[s[end]] = end;
            end ++;
            max_len = max(max_len, end - begin) ;
        }
        return max_len;
    }
};

之前错误的思路:

比如test case "abcabcbb", 使用两个指针begin, end分别指向0,1, 然后end向后走,如果当前指向的字符在前面出现过,就将begin指针指向之前出现过位置的后面一个位置,在例子中,就是当begin = 0, end = 3的时候,发现a在前面出现过,位置是0,所以begin指针指向1,然后计算长度。但是当遇到"abba"这种case的时候,就会出现问题,end指针指向3的时候,发现字符'a'在位置0出现过,就会把begin 指针指向位置0的下一个位置,但是中间的bb是有重复的,所以应该跳过bb。

改正后的思路:

思考如何跳过"bb"呢?当重复字符的下标小于begin的时候,就说明会包含重复的部分,因为只有当有重复的字符出现的时候,begin才会往前走,begin没有后退的可能。所以,只需要添加begin <= my_map[s[end]] 判断条件就可以输出正确的结果了。

分析:

算法的时间复杂度是 O(n), 空间复杂度O(n), 其实这里还可以减小空间复杂度,或者说平均空间复杂度,这里就不在说了。