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

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

示例 1:

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

示例 2:

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

示例 3:

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

解题思路
用left和right设置左右指针,分别标识字符串不重复字段的左部和右部。右指针不断移动直到遇到重复字符,同事更新长度。
当右指针所指元素已经查找过是,将左指针移到重复元素的后一位。

方法一:
  用set方法,进而用contain判断是否重复
class Solution {
    public int lengthOfLongestSubstring(String s) {
        int res = 0, left = 0, right = 0;
        //滑动窗口解法1:set结构
        Set<Character> set = new HashSet<>();
        while(right < s.length()){
             //contains是包涵的意思,就是用来检查有没有在录入的连续的map里面
            if(!set.contains(s.charAt(right))){
                set.add(s.charAt(right++));
                res = Math.max(res,set.size());
            }else{
                //左指针向右移动,直到移动到重复元素
                set.remove(s.charAt(left++));
            }
        }
        return res;
    }
}

方法二:

  用的map方法,这里一开始没太弄懂,原来是吧left指针移至容器内的字符后一位,一开始理解错了。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        //滑动窗口解法:map结构
        Map<Character,Integer> map = new HashMap<>();
        int res = 0;
        for(int left = 0, right = 0; right < s.length(); right++ ){
            if(map.containsKey(s.charAt(right))){
          //需要向后移至到重复字符后一位 left
= Math.max(left, map.get(s.charAt(right)) + 1); } res = Math.max(res, right - left + 1); //根据map的性质,当存储重复元素时,新的value值即索引将会覆盖旧值 map.put(s.charAt(right), right); } return res;
abcacs } }

方法三:

  这里我们可以建立一个256位大小的整型数组来代替HashMap,这样做的原因是ASCII表共能表示256个字符,所以可以记录所有字符,然后我们需要定义两个变量res和left,其中res用来记录最长无重复子串的长度,left指向该无重复子串左边的起始位置,然后我们遍历整个字符串,对于每一个遍历到的字符,如果哈希表中该字符串对应的值为0,说明没有遇到过该字符,则此时计算最长无重复子串,i - left +1,其中i是最长无重复子串最右边的位置,left是最左边的位置,还有一种情况也需要计算最长无重复子串,就是当哈希表中的值小于left,这是由于此时出现过重复的字符,left的位置更新了,如果又遇到了新的字符,就要重新计算最长无重复子串。最后每次都要在哈希表中将当前字符对应的值赋值为i+1。代码如下:

class Solution {
    public int lengthOfLongestSubstring(String s) {
     //滑动窗口方法:数组存储ASCII值
        int[] m = new int[256];
        int res = 0;
        //try extend the rang [left, right]
        for(int left = 0, right = 0; right < s.length(); right++){
            //m[s.charAt(right)]返回一个重复字符的地址
            left = Math.max(m[s.charAt(right)], left);
            res = Math.max(res, right - left + 1);
            m[s.charAt(right)] = right + 1;
        }
        return res;
    }
}

分析表格

0 1 2 3 4 5 6
a b c a b c a


right left res
m[s.charAt(right)]
0 0 1 1
1 0 2 2
2 0 3 3
3 1 3 4
4 2 3 5


原文地址:https://www.cnblogs.com/xiemingjun/p/9636343.html