当前位置: 首页 > news >正文

【力扣03】无重复字符的最长子串

题目

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

示例 1:

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

示例 2:

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

示例 3:

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

滑动窗口技术

思路:


这道题主要用到思路是:滑动窗口

什么是滑动窗口?

其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列!

如何移动?

我们只要把队列的左边的元素移出就行了,直到满足题目要求!

一直维持这样的队列,找出队列出现最长的长度时候,求出解!

时间复杂度:O(n)

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        if not s:return 0
        left = 0
        lookup = set()
        n = len(s)
        max_len = 0
        cur_len = 0
        for i in range(n):
            cur_len += 1
            while s[i] in lookup:
                lookup.remove(s[left])
                left += 1
                cur_len -= 1
            if cur_len > max_len:max_len = cur_len
            lookup.add(s[i])
        return max_len

这段代码使用滑动窗口技术来找出字符串中最长的无重复字符子串的长度。以下是逐行解释:

  1. if not s: return 0
    检查输入字符串是否为空,如果为空则直接返回0。

  2. left = 0
    初始化左指针left为0,表示当前窗口的起始位置。

  3. lookup = set()
    创建一个空集合lookup,用于记录当前窗口中的字符。

  4. n = len(s)
    计算字符串s的长度,并赋值给变量n

  5. max_len = 0
    初始化最长子串长度max_len为0。

  6. cur_ len = 0
    初始化当前窗口长度cur_ len为0。

  7. for i in range(n):
    遍历字符串中的每一个字符,索引为i

  8. cur_ len +=1
    进入循环后,先将当前窗口长度增加1,假设当前字符可以加入窗口。

  9. while s[i] in lookup:
    检查当前字符s[i]是否已经在当前窗口中存在。如果存在,则需要调整窗口左边界:

    a. lookup.remove(s[left])
    移除集合中的左指针指向的字符,表示该字符不再属于当前窗口。

    b. left +=1
    将左指针向右移动一位,缩小窗口范围。

    c. cur_ len -=1
    由于移除了一个字符,当前窗口长度减1。

  10. if cur_ len > max_len: max_len = cur_ len
    检查当前窗口长度是否为最大值,并更新max_len

  11. lookup.add(s[i])
    将当前字符s[i]添加到集合中,表示该字符已加入当前窗口。

  12. return max_len
    遍历结束后,返回最长无重复子串的长度max_len

#include<string.h>  //首先额外引入一个新的字符串库
int lengthOfLongestSubstring(char* s) {
    int len=strlen(s);  
    //得到字符串的长度
    int i = 0;      
    //i是循环变量,从第一个字符开始找最长的无重复字母的子串
    int result = 0; 
    //result 为最后的返回的结果,求长度最长时,result至为0;求长度最短时,result至为INT32_MAX
    int count = 0;  //count 为每次循环的最长的无重复字母的子串的长度
    int b;  //b 为递归调用循环变量
    while (s[i])
    {
        int flag = 1;   //flag 为标志变量,首先至为1
        int j;  //里层循环的变量j
        for (j = 0; j < i; j++)
        {
            if (s[i] == s[j])//如果找到重复的的字母,那么就
            {
                flag = 0;   //标志变量至为0
                b = j;      //递归变量b赋值为j,即在子串的与s[i]重复的第一个字母
                break;      //跳出里层循环
            }
        }
        if (flag == 1)//如果遍历了一遍,如果没发现重复的字母,flag还是等于1
        {
            i++;     
            count++;    //子串的长度加1
            result = result > count ? result : count; //更新result的结果:count和原来result中最大的数
        }
        else
        {
            break;  //否则,退出外层循环
        }
        b = i;  //如果i=1时,s[i](即s[b],即s[1])和s[1]相同时,递归时直接往后移一位就行;;当i>1,也是从子串的与s[i]重复的第一个字母s[b]下一个字母————s[b+1]开始,
    }
    // 设置递归出口条件
    if (b+1<len) //注意不建议*(s+b+1),这样算是空指针解引用,在力扣上报错了,但在VS上没报错  //所以必须保证b+1<len
    {
        count = lengthOfLongestSubstring(s+b+1);
        result = result > count ? result : count;//必须要有这一步,否则也会出错
        //将递归的结果与上级函数的result比较
    }
    return result;
}

相关文章:

  • 4月11日随笔
  • 【深入浅出 Git】:从入门到精通
  • onenote的使用技巧以及不足之处
  • 【网络安全 | 项目开发】Web 安全响应头扫描器(提升网站安全性)
  • 【路由交换方向IE认证】BGP常用属性(除公认必遵外的属性)
  • uniapp离线打包提示未添加videoplayer模块
  • 分布式水文模型丨WRF-Hydro建模与案例应用、从软件安装,到案例实践
  • 【IDEA】创建 SpringBoot 项目连接 MySQL
  • C# net CMS相关开源软件 技术选型 可行性分析
  • 0411 | 软考高项笔记:项目立项
  • 大模型本地部署系列(4) Ollama部署Gemma 3大模型
  • C++ 大数相加(简要版)
  • 整体 Vue 系统框架下的优化方案,旨在减少内存用量并提升整体性能
  • 【时时三省】(C语言基础)用switch语句实现多分支选择结构 例题
  • MATLAB编写的机械臂控制仿真程序,它主要实现了对一个二连杆机械臂的运动控制仿真,比较了PID控制和非线性模型预测控制两种方法在机械臂轨迹跟踪任务中的性能
  • 【发布】dtns协议的js-sdk(实现a2a协议:agent2agent)
  • 本地搭建直播录屏应用并实现使用浏览器远程控制直播间录屏详细教程
  • 量子测试时代,会来得比我们想象中更快?
  • 02-MySQL 面试题-mk
  • KDD 2025 顶会最新力作,多变量时间序列预测登顶!
  • 企业做网站etp和源程序/深圳市住房和建设局官网
  • 网页设计作品网站/seo如何优化
  • 金华电子商务网站建设/四川网络推广推广机构
  • 做赌博网站违法吗/百度导航官网
  • 荆州松滋网站建设/网页设计需要学什么
  • 免费收录网站大全/百度云超级会员试用1天