[Java恶补day8] 3. 无重复字符的最长子串

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

示例 1:

输入: s = "abcabcbb"

输出: 3

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

示例 2:

输入: s = "bbbbb"

输出: 1

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

示例 3:

输入: s = "pwwkew"

输出: 3

解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

提示:

0 <= s.length <= 5 ∗ 10 4 5 * 10^4 5∗104

s 由英文字母、数字、符号和空格组成


知识点:

滑动窗口、哈希表、字符串


根据官解,有以下结论

①一旦涉及出现次数 ,就需要使用哈希表。

字符串类型的题:key=字符,value=出现次数

②一旦涉及子串 ,通常能通过滑动窗口进行动态扩张


解:

首先,对空字符串进行处理,直接返回0,提高效率。

然后,定义变量max存储最长子串的长度。定义一个HashMap,存储每个字符在字符串中出现的下标。此外,定义一个start变量,表示滑动窗口的起始下标。

接着,for循环遍历整个字符串,通过 s.charAt(i)获取当前遍历的字符

在for循环内:

1、若当前遍历的字符没在map中,那么通过map.put(s.charAt(i), i);将当前字符加入map,能保证滑动窗口内无重复字符,这里键值对的value=i,表示的是当前遍历的字符的下标。

2、若当前遍历的字符在map中,我们要进行if-else判断:

①若当前遍历的这个重复字符,目前在滑动窗口内,则移动滑动窗口的左边界 start到当前遍历的字符的下一个位置 。原因是:既然重复的字符在滑动窗口内,如果左边界还是在滑动窗口内的这个字符的位置,或者是滑动窗口内的这个字符的左侧,整个滑动窗口还是重复的,没有必要这么做,因此我们直接让 start移动到 map.get(s.charAt(i)) + 1的位置

这里以测试样例3说明原因中的第一点。第二点根据文字描述即可想象出情况,就不例举了。

②若当前遍历的这个重复字符,在滑动窗口前面,则不处理。因为我们看的就是滑动窗口内的情况,不考虑滑动窗口外的情况

在上面的重复字符处理结束后,通过map.put(s.charAt(i), i);将当前字符加入map。

最后,我们通过Math.max(max, i - start + 1)获取每次滑动窗口遍历的最长子串的长度。

最终返回max变量。

java 复制代码
class Solution {
    public int lengthOfLongestSubstring(String s) {
        //空字符串直接返回
        if (s.length() == 0) {
            return 0;
        }

        //最长子串长度
        int max = 0;
        //HashMap存储每个字符出现在字符串中的下标
        Map<Character, Integer> map = new HashMap<>();
        //滑动窗口起始下标
        int start = 0;
        //end = i: 隐式表示滑动窗口结束下标

        //遍历字符串的每个字符
        for (int i = 0; i < s.length(); i++) {
            //已出现过当前遍历的字符
            if (map.containsKey(s.charAt(i))) {
                //若当前遍历的这个重复字符,目前在滑动窗口内,则移动start到这个重复字符的下一个位置
                if (map.get(s.charAt(i)) >= start && map.get(s.charAt(i)) <= i) {
                    start = map.get(s.charAt(i)) + 1;
                }
                //若当前遍历的这个重复字符,在滑动窗口前面,则不处理
                else if (map.get(s.charAt(i)) < start) {
                    start = start;
                }
            }
            //将当前遍历字符加入map
            //1.当前遍历字符不在map中,则滑动窗口内必无重复字符
            //2.当前遍历字符在map中,而此时已完成滑动窗口边界的处理,此时字符也不会在滑动窗口中重复出现
            map.put(s.charAt(i), i);
            //获取当前子串的长度
            max = Math.max(max, i - start + 1);//数组下标从0开始,则子串长度需要加1
        }

        return max;
    }
}

引用:

  1. java遍历String字符串的方法
相关推荐
星乐a几秒前
String 不可变性与常量池深度解析
java·开发语言
captain3761 分钟前
ACM模式下Java输入输出函数为什么会超时?及解决方法
java·开发语言
田梓燊3 分钟前
leetcode 48
算法·leetcode·职场和发展
程序员老邢6 分钟前
【产品底稿 04】商助慧 V1.1 里程碑:爬虫入库 + MySQL + Milvus 全链路打通
java·爬虫·mysql·ai·springboot·milvus
mmz12078 分钟前
深度优先搜索DFS2(c++)
c++·算法·深度优先
6Hzlia8 分钟前
【Hot 100 刷题计划】 LeetCode 169. 多数元素 | C++ 哈希表基础解法
c++·leetcode·散列表
2601_950703949 分钟前
Java安全编程与静态分析实战
java
好家伙VCC9 分钟前
**发散创新:基于Python与OpenCV的视频流帧级分析实战**在当前人工智能与计算机视觉飞速发展的背景下
java·人工智能·python·计算机视觉
米粒110 分钟前
力扣算法刷题 Day 38 (打家劫舍专题)
算法·leetcode·职场和发展
SimonKing10 分钟前
大V说’AI替代不了你’,但现实是——用AI的人正在替代你
java·后端·程序员