算法学习100天——13 滑动窗口

题目地址(3. 无重复字符的最长子串)

https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

题目描述

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

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

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

示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
     
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成

思路1

此题一开始,我没学过滑动窗口,就用HashMap处理的,遍历数组,每一次拿到字符,存入HashMap中,字符作为key,下标作为value,如果已存在于map中,则拿到之前那个字符的下标,将指针 i 回滚到“被重复字符”的下一个下标位置,其实思想类似于滑动窗口,但是时间复杂度远大于滑动窗口,因为我将 i 回滚了

代码

HashMap求解
class Solution {
    public int lengthOfLongestSubstring(String s) {
        HashMap<Character, Integer> map = new HashMap<>();
        int length = 0;
        for(int i = 0; i < s.length(); i++){
            if (map.get(s.charAt(i)) != null){
                length = Math.max(map.size(), length);
                // 指针回滚
                i = map.get(s.charAt(i)) + 1;
                map.clear();
            }
            map.put(s.charAt(i), i);
        }
        return Math.max(map.size(), length);
    }
}

结果

执行用时:100 ms, 在所有 Java 提交中击败了8.32%的用户

内存消耗:41.6 MB, 在所有 Java 提交中击败了16.68%的用户

【enmmmmmmm,这个执行用时真的很打击人,哈哈哈哈哈哈】

思路2

滑动窗口,利用两个指针+一个Set维护一个不重复的窗口,两个指针维护窗口的边界,利用Set始终保持窗口内元素不重复。遍历字符串,以每一个字符为左边界,这样就找到了所有不重复的字数组,再每一次取长度最小的窗口记录,最后得到结果

滑动窗口
class Solution {
    public int lengthOfLongestSubstring(String s) {
        int res = 0;
        int rp = -1;
        HashSet<Character> set = new HashSet<>();
        for(int i = 0; i < s.length(); i++){
            // 除了最开始时,后面每一轮都移除i前面的元素
            // 移除的原因:i作为左边界,已经向右收缩了一个,故s.charAt(i - 1)不再滑动窗口里面
            if(i != 0){
                set.remove(s.charAt(i - 1));
            }
            // 当set中没有重复的字母(即:滑动窗口长度最大)时,右边界一直右移,直到字符串遍历完全
            while((rp + 1) < s.length() && !set.contains(s.charAt(rp + 1))){
                set.add(s.charAt(rp + 1));
                rp ++;
            }
            // 将最大长度赋值给res;
            res = Math.max(res, set.size());
        }
        return res;
    }
}

结果

执行用时:6 ms, 在所有 Java 提交中击败了53.01%的用户

内存消耗:41.4 MB, 在所有 Java 提交中击败了28.44%的用户

【不是100%,说明还有更优解,评论区第一是最优解,但是我看不懂,学会了再补上。。。】

posted @ 2022-03-12 10:16  浪漫主义程序员  阅读(25)  评论(0编辑  收藏  举报