3. 无重复字符的最长子串(LeetCode)

题目描述


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

示例 1:

输入: s = "abcabcbb"

输出: 3

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

条件分析


  1. 字符无重复;
  2. 子串有连续的字符构成

解题思路(滑动窗口)


  1. 将字符串拆分为字符数组,定义一个变量maxLen存储最长子串的长度;
  2. 定义两个下标left,right,如果没有重复,取maxLen为当前长度与maxLen的最大值,如果发现right和已有字符重复,则left=重复字符下标+1,right++,直到right到达末尾;
  3. 如何判断字符在数组中已经出现?可以考虑用一个数组freq将每个字符出现的下标记录下来,值-1代表未出现,否则存储的是元素的下标。注意在重置left的时候,老的left和新的left之间的freq元素也进行更新为-1,表示不再存在

编码如下

 public int lengthOfLongestSubstring(String s) {
    char[] cs = s.toCharArray();
    int left = 0; // [left,right]为最大不重复子串
    int right = -1;
    int maxLen = 0;
    
    int[] freq = new int[256]; // 存储元素的下标,初始情况下所有元素都不存在
    for (int i=0; i<freq.length; i++) {
        freq[i] = -1;
    }
    while (right < cs.length-1) {
        right++;
        // 元素不存在,计算最大值
        if (freq[cs[right]] == -1) {
            maxLen = max(maxLen, (right - left + 1));
        } else {
            // 元素存在,取出存在元素的下标+1,也就是left要移动到的新位置
            int newLeft = freq[cs[right]] + 1;
            // 把老的left和新的left之间的元素都设置为不存在,相当于重置
            while (left < newLeft) {
                freq[cs[left++]] = -1;
            }
            left = newLeft;
        }
        freq[cs[right]] = right;
    }
    return maxLen;
}

private int max(int max, int newMax) {
    if (newMax > max) {
        max = newMax;
    }
    return max;
}
posted @ 2021-07-08 20:56  咸与维新  阅读(73)  评论(0)    收藏  举报