无重复字符的最长子串

116 阅读3分钟

这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

1.LeetCode无重复字符的最长子串

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

示例 1:

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

可以使用滑动窗口实现,窗口从左往右慢慢拉大,只要保证窗口字符不重复,那么移动到最后时,最大的窗口值就是目标值。

使用两个指针表示窗口的边界,左边界为最开始的位置,右边界往右边一个一个遍历字符,同时用一个哈希表记录遍历的字符,key存储字符,value存储下标,可以当做右指针,当做窗口内的字符,同时可以比较方便的判断字符是否重复,如果遇到了重复存在哈希表内的字符时就需要移动左指针,将左指针往右移动到重复字符的位置,以保证窗口字符不重复,后面在正常添加字符及其下标到哈希表,最后再取最大的窗口大小,就是两个下标差。

例如aabcab 左指针默认在a字符左边,右指针指向a字符,左指针-1,右指针0,最大长度默认为0,哈希表内容为空,遍历字符串,用右指针往后移动 第一次为(a)abcab 第一次获取下标0字符为a,查询a字符不存在哈希表,将a字符和下标添加到哈希表,此时最大字符串长度为1(右下标-左下标)。 第二次为a(a)bca 往后移动遇到字符a,与哈希表字符比较发现是重复的,此时需要移动左指针,将左指针往右移动到重复字符处下,取最大的下标值。同时最大字符长度还是1。 第三次为a(ab)ca 继续往右遍历字符b,比较哈希表,无重复,添加字符,取最大字符长度为2。 第四次为a(abc)a 继续往右遍历字符c,比较哈希表也无重复,添加字符后取最大长度为3。 第五次为aa(bca) 继续往右遍历字符a,发现与哈希表重复,需要移动左指针,此时字符最大长度为3。

public int lengthOfLongestSubstring(String s) {
    // 最大长度
    int maxLength = 0;
    // 左指针
    int leftPointer = -1;
    // 哈希表判断字符是否重复
    Map<Character, Integer> map = new HashMap<Character, Integer>();
    // 当前遍历的字符
    char currentChar;
    // 右指针循环遍历
    for (int rightPointer = 0, length = s.length(); rightPointer < length; rightPointer++) {
        currentChar = s.charAt(rightPointer);
        if (map.containsKey(currentChar)) {
            // 哈希表里面存在,指针往后移动到存在的字符处,max保证往后移动
            leftPointer = Math.max(leftPointer, map.get(currentChar));
        }
        // 添加当前字符及其下标到哈希表
        map.put(currentChar, rightPointer);
        // 取得子字符串最大值
        maxLength = Math.max(maxLength, rightPointer - leftPointer);
    }
    return maxLength;
}