目 录CONTENT

文章目录

Leetcode 无重复字符的最长子串

小王同学
2024-09-18 / 0 评论 / 0 点赞 / 39 阅读 / 0 字

Leetcode 无重复字符的最长子串

力扣传送门

解题思路:

这道题目我们可以使用滑动窗口的思路。

滑动窗口是一种管理两个指针(通常是窗口的起始和终止位置)的技术,通过这两个指针可以表示字符串中的一个区间。当这个区间内的元素满足题目要求时,我们尝试扩大窗口的大小(即移动结束指针);当不满足要求时,我们需要通过移动开始指针来缩小窗口,直到再次满足条件。

无重复字符的最长子串

关键词:无重复,最长

我们肯定要记录哪个字符是重复的吧,这个我们可以使用HashMap来进行存储对应的字符,key为字符,value为字符对应的下标。然后呢,我们准备两个指针来控制滑动窗口的大小,这两个指针为fast和slow,初始化的话我们都从0开始,最后我们题目需要返回一个结果值,这个结果值就是无重复字符的最长子串的大小,我们定义为max。

首先,我们循环遍历这个字符串,这里我们可以先把字符串转换成数组,方便我们后续对字符串的读取,接着判断hashmap里面是否存在当前的字符,如果存在的话,说明遇到重复的字符了,那么我们该如何处理窗口大小呢?

我们思考一下,是不是应该将slow的指针进行变化了。因为我们每次循环遍历这个字符串的时候fast已经在增加了,我们只需要考虑slow的指针变化,这时候我们需要将slow使之指向重复字符上一次出现位置的下一个位置,注意这句话的理解, 我们将slow指向重复字符的上一次出现的位置的下一个位置。这一步操作的目的是为了确保从 slowfast(包括 fast 指向的位置)的窗口中不存在重复的字符。

fast 指针在字符串中前进并发现一个重复字符时,这意味着当前考虑的窗口(从 slowfast)已经包含了一个与 fast 指向相同的字符。为了维护窗口内的字符唯一性,我们需要排除旧的重复字符及其之前的所有字符。通过将 slow 指针移动到重复字符之前的位置的下一个位置,我们可以保证新的窗口不包含重复字符。

比如下面这张图,当f走到第二个w的时候,s需要走到w上一次出现的位置的下一个位置,那么就是w的第二次出现的位置,再例如,当f走到第三个w的位置时候,s需要指向w上一次出现的位置(即第二次出现w的位置)的下一个位置,即k的位置。这一点是最重要的,如果理解了这个slow的更新逻辑,那么下面就好说了

我们不管更新完slow还是没更新slow,我们都需要将当前遍历的fast装入到hashmap里面,并且紧接着更新我们的结果值max,max的每次计算都是取的max和fast-slow+1这两个值的最大值,fast-slow+1 也就是我们计算的不重复的字符的长度。

最后返回max的值即可。

具体的流程可以看下面手写的步骤图。

无重复字符的最长子串1.jpg

无重复字符的最长子串2.jpg

代码实现:

class Solution {
    public int lengthOfLongestSubstring(String s) {
        // 如果输入的字符串为空或长度为0,直接返回0
        if(s == null || s.length() == 0){
            return 0;
        }
        // 将字符串转换成字符数组
        char[] ch = s.toCharArray();
        // 快指针
        int fast = 0;
        // 慢指针
        int slow = 0;
        // 用于记录最大无重复字符的子字符串长度
        int max = 0;
        // 哈希表用于存储字符和其最新的索引位置
        HashMap<Character, Integer> hashmap = new HashMap();
        // 遍历字符数组
        for(; fast < ch.length; fast++){
            // 如果字符已存在于哈希表中,说明出现了重复字符
            if(hashmap.containsKey(ch[fast])){
                // 更新慢指针的位置到重复字符的下一个位置,但不回退
                slow = Math.max(slow, hashmap.get(s.charAt(fast)) + 1);
            }
            // 更新哈希表中的字符位置
            hashmap.put(ch[fast], fast);
            // 计算当前无重复字符的子字符串长度并更新最大长度
            max = Math.max(max, fast - slow + 1);
        }
        // 返回最大长度
        return max;
    }
}

复杂度分析

  • 时间复杂度:O(N),其中 N 是字符串的长度。每个字符只被处理一次。
  • 空间复杂度:O(min(M, N)),其中 M 是字符集的大小(如 ASCII 字符集是 128)。这是因为哈希表最多存储这么多键值对。
0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区