【中等】3-无重复字符的最长子串 Longest Substring Without Repeating Characters

题目

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

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

Example1

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

Example2

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

Example3

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

来源:力扣(LeetCode)
链接:https://leetcode.com/problems/longest-substring-without-repeating-characters

解题思路

p.s. 字符串S[i:j]表示从字符S[i]开始到S[j]截止(不包括S[j])的子字符串

首先,看到这道题第一想法仍然是暴力过程:从每一位开始,向后查找到使得区间没有重复字符的最大位置截止,即为一个无重复字符子串,最后得到的最大长度就是问题的解。当然,很明显这种方法是十分复杂不可取的。

此时,我们分析是什么过程使得暴力过程如此复杂?假设从第i位开始,依次检查重复字符,发现到第j位都没有重复字符,而第j+1位上出现了与第t位重复的字符(i<=t<=j),按照暴力破解流程,我们将从第i位开始的最长子串大小设置为j-i+1,然后又从第i+1位开始重复上述查询过程。

这时,出现了第一个重复的检查过程:第i+1到第j位上明显是没有重复字符的,如果再次进行比较就是多余的过程,所以,只需要检查第j+1位在字符串[i+1:j+1]上是否有重复字符即可

此时第二个重复过程也出现了:j+1位在子串[i+1:j+1]上是否重复这个结果我们已经知道了,即如果i=t,那么没有重复,如果t>i,那么自然在第t位上与j+1位重复,同理,从第i+1到第t位的计算过程都是可以省略掉的。

随之第三个重复过程就是,在子串[t+1:j+2]中一定没有重复子串,所以后续检查j+2位在子串[t+1:j+2]中是否有重复子串即可

也就是说,如果已知子串[i:j+1]是字符串的无重复子串,而第j+1位与第t位发生重复,那么对于i+1到t,无论从哪一位开始作为无重复子串的起始位,都没有办法得到一个长度大于j-i+1的字符串,因为一定会同时包含t位和j+1位,如果想要找到后续的字符串,只能从第t+1位开始算起,又因为第t+1位到第j+1位一定没有重复字符串,所以只需要从j+2位继续检查的过程。

这也是常说的滑动窗口

由此我们得到这道题的算法:

对于一个字符串s,初始化开始位置为0,查询位置为1,长度为1,已知子串窗口为s[0:1],依次检查待检查位与子串窗口是否有重复字符,如果一直到第j位都没有重复字符,字串逐步更新为s[0:j+1](扩大子串长度),最大长度为l;如果在第t位有重复,则开始位置设置为t+1,待检查位为j+2,重复上述过程

代码

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s.length() <= 1) return s.length();
        int max = 1;
        int last = -1;
        for(int i = 1; i < s.length(); ++i){
            for(int j = last+1; j < i; ++j){
                if(s[i] == s[j]){
                    last = j;
                }
            }
            max = max < i-last ? i-last : max;
        }
        return max;
    }
};
posted @ 2020-04-14 17:17  陌良  阅读(142)  评论(0编辑  收藏  举报