leetcode3-无重复字符的最长子串

149 阅读2分钟

题目

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

示例 1:

输入: s = "abcabcbb"

输出: 3

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

来源:力扣(LeetCode)

链接:leetcode.cn/problems/lo…

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

代码

public class Leetcode3 {
    public int lengthOfLongestSubstring(String s) {
        if(null==s||s.length()==0){
            return 0;
        }
        // 记录最大值
        int max = 0;
        // 记录滑动窗口的左指针,代表移动到了那个位置,后面计算最大值时,需要剪掉移动的距离
        int left = 0;
        // key用来判断是否有重复字串,value用来记录当前字符的最新位置
        HashMap<Character,Integer> map = new HashMap<>();
        for(int i=0;i<s.length();i++){
            if(map.containsKey(s.charAt(i))){
                // 更新left的值,为对应重复的值下标+1(代表滑动窗口移动到重复的那个字母后面)
                left = Math.max(left,map.get(s.charAt(i))+1);
            }
            map.put(s.charAt(i),i);
            // 计算最大值,即减去滑动窗口移动的距离
            max = Math.max(max,i-left+1);
        }
        return max;
    }
}

解析

典型的滑动窗口题目;

第一反应: 肯定有一个右指针一直在往右边遍历,并且一直和前面对比是否有重复的,如果遇到重复的就把左边的指针往右移动,然后一直比较,知道找到没有重复的那个点,然后在让右边继续走;这种思维思考下来就会用队列的形式去做,显然复杂度很高

优解: 对于这个题目,只需要弄懂一个表达式(i-left+1),我们要得到是一个最长子串的长度(如果需要子串的值,到时候记录下下标即刻),显然只需要记录下滑动窗口左指针的下标,然后用当前下标-left+1就得到了我们需要的答案。然后map就很好的可以用来记录每个节点的下标,然后每次遍历节点,都去更新节点对应的最大下标;这样当遇到重复节点时,可以直接将左指针,移动到重复节点的上次位置+1,即(map.get(s.charAt(i))+1),这样就省去了上面说的需要左指针一步一步确定重复点的问题;然后因为直接跳到重复点的问题,如果下一个节点与重复点前面的节点重复,可能回导致left的值被小值覆盖,所以需要取max;例如abba这种结构,推敲便知