[LeetCode][M0003]无重复字符的最长子串(Java)(滑动窗口)

本文介绍了一种使用滑动窗口算法解决LeetCode上最长无重复字符子串问题的方法,通过动态调整窗口大小,高效找到目标子串长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

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

示例 1:

输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

示例 2:

输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


解题思路:

一般这种寻找连续的字符串之类的题都是滑动窗口或者动态规划的解法,这题我用的滑动窗口。
想象一下,字符串是长长的一排,现在有一个不定长的窗口去框住最长的不重复字符串,
分步来看【举例来说,abcabcda】:
窗口从头开始,窗口长为零,窗口内没有重复符号,窗口就像右拓展一位【[]abcabcda --> [a]bcabcda】
一直向右拓展,检测到即将添加的符号在窗口内出现过,就将窗口的左端向右收缩【[abc]abcda --> a[bc]abcda】
这样只要有一个char[] let数组记录窗口内出现过的字符,还有cur变量当前窗口内个数,以及res变量纪录最大值。

反思错误:

①没有注意到是所有字符,以为只有小写字母,所以char[]数组大小设置为26。【常用ascll码最大值为127,应设置长度128】
②居然让窗口没有右滑,无限循环了。

Java代码:

class Solution {
    public int lengthOfLongestSubstring(String s) {
        // if(s==null || s.equals(""))return 0;//我上来就写上了,其实不需要。
        
        int[] let = new int[128];//因为ascll码0~127
        int l=0,r=0;//窗口的左右端
        int res = 0;//结果
        
        char[] cs = s.toCharArray();
        int len = cs.length;//字符串长度
        
        int cur = 0;//记录窗口内字符个数
        
        //滑动窗口具体实现,l,r不能越界
        while(r<len && l<=r){
            //let==0:窗口内没有当前字符
            if(let[cs[r]] == 0){
                let[cs[r]] = 1;//将当前字符纳入窗口内
                ++r;//窗口右扩
                ++cur;//窗口内字符数加一
                res = res>cur?res:cur;//纪录最大值
            }
            //let==1:窗口内有当前字符
            else{
                //只要当前字符在窗口内存在,就循环缩小左端,直至let==0
                while(let[cs[r]]!=0 && l<r){
                    let[cs[l]] = 0;//缩小左端代表:左端该值退出窗口
                    ++l;//左端右移
                    --cur;//窗口内字符数减一
                }
            }
            
        }
        return res;
    }
}

运行结果:

执行用时 :6 ms, 在所有 Java 提交中击败了98.84%的用户
内存消耗 :38 MB, 在所有 Java 提交中击败了90.19%的用户

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值