算法-滑动窗口-最长无重复子串详细题解

69 阅读2分钟

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

示例 1:

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

示例 2:

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

示例 3:

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

思路:

典型的滑动窗口问题,采用双指针的策略,不断记录左右指针之间的距离;详细步骤如下:

  1. 左右指针都初始化为0;初始化最长无重复字符串的长度为0;
  2. 右指针向右移动,判断右指针的元素是否与前面的元素重复:
  • a. 不重复则继续向右滑动,记录左右指针之间字符串的长度,和初始化的长度对比,取最大值;
  • b. 重复,左指针向右滑动,滑动过程中同时剔除元素,直到不存在与右指针指向字符相同的字符为止
  1. 将右指针指向的字符加入队列;
  2. 记录左右指针之间字符串的长度,和初始化的长度对比,取最大值;

如此循环,直到右指针指向字符串的最后一个字符;

代码:

详细代码和注释如下:

public static int lengthOfLongestSubstring(String s) {
    //定义一个set用于进行元素判重
    Set<Character> set = new HashSet<>();
    //初始化长度以及左右指针
    int len = 0;
    int left = 0;
    int right = 0;
    //右指针不断向右滑动,直到字符串结束;过程中段记录最长子串的长度
    while(right<s.length()){
        //如果右指针的字符在当前set中存在,则滑动左指针,直到不存在为止,滑动过程中剔除相关元素
        while(set.contains(s.charAt(right))){
            set.remove(s.charAt(left));
            left++;
        }
        //将当前字符加入到set集合中
        set.add(s.charAt(right));
        //计算截止目前最长的无重复字符的子串的长度
        len = Math.max(len, right - left + 1);
        right++;
    }
    return len;
}