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

题目描述

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

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

解析

算法技巧:

应用HashMap存储遍历的字符及其坐标索引,以减少遍历字符串次数,利用空间换取时间

实现方法:

方法一:暴力法依次遍历字符串中每个字符作为开头的最长子串,在众多子串中选出最长子串。
方法二:在方法一基础上每次查找新的字符开头的子串时,记录已经存在的字符,这样可以消除为判断是否重复而往回校验的时间消耗。
方法三:遍历一趟字符串,并且不走回头路。需要记录子串开始的位置head,和HashMap记录已经存在的字符,如果遇到当前字符已经存在则统计当前的最长子串,head不需要移动到1,而是移动到重复字符的后一位。例如,s[j]在s[i]~s[j-1]存在,下标为k(i <= k <= j-1 ),则新的子串从k + 1开始即可,因为i与k之间开头的字符不可能存在长度超过j-i的不重复子串。同时,考虑一种特殊情况,如果HashMap中存在当前字符,但是当前字符却不在遍历的区间,那么此时head不需要移动,但是要更新HashMap。

代码
public int lengthOfLongestSubstring(String s) {
    int head = 0, tail = head, longest = 0;
    Map map = new HashMap<>();
    while(tail < s.length()){
        char c = s.charAt(tail);
        Integer i = map.get(c);
        if(i != null){//HashMap存在当前字符c
            longest = (tail - head) > longest ? (tail - head) : longest;//遇到重复时更新最长子串长度
            head = head > i ? head : i + 1;//判断是否在当前区间内,决定是否改变head
        }
        map.put(c, tail);//新插入或者更新HashMap
        tail++;
    }
    return (tail - head) > longest ? (tail - head) : longest;
}

你可能感兴趣的:(无重复字符的最长子串(LeetCode--3.无重复字符的最长子串))