• leetcode:滑动窗口----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 * 104
    • s 由英文字母、数字、符号和空格组成

    因为s由英文字母、数字、符号和空格组成,符合ASCII码,故采用ASCII码大小的数组,使用ASCII码为下标,记录每个字符出现的最后位置。并在每次循环的开始,将left更新为上一次该字符出现的位置+1。

    滑动窗口算法的基本原理:

    1. 初始化窗口:定义两个指针,通常是leftright,并初始化为字符串或数组的起始位置。

    2. 滑动窗口right指针逐个增加,尝试扩大窗口,同时更新解的答案。

    3. 更新解的答案:当满足题目条件时,我们需要更新当前的最优解。

    4. 收缩窗口:如果当前窗口不满足题目的条件,移动left指针缩小窗口,直到满足条件为止。

    示例分析:

    以题目"abcabcbb"为例,详细步骤如下:

    1. 初始化:left = 0, right = 0, maxLen = 0, charIndex[] = {-1, -1, -1, ...}

    2. right逐个增加:

      • s[0] = 'a'charIndex['a'] = -1,更新为charIndex['a'] = 0,窗口长度为1maxLen = 1
      • s[1] = 'b'charIndex['b'] = -1,更新为charIndex['b'] = 1,窗口长度为2maxLen = 2
      • s[2] = 'c'charIndex['c'] = -1,更新为charIndex['c'] = 2,窗口长度为3maxLen = 3
      • s[3] = 'a'charIndex['a'] = 0,左指针移动到1,窗口变为"bca",窗口长度为3maxLen保持不变。
      • s[4] = 'b'charIndex['b'] = 1,左指针移动到2,窗口变为"cab",窗口长度为3maxLen保持不变。
      • s[5] = 'c'charIndex['c'] = 2,左指针移动到3,窗口变为"abc",窗口长度为3maxLen保持不变。
      • s[6] = 'b'charIndex['b'] = 1,左指针移动到4,窗口变为"bca",窗口长度为3maxLen保持不变。
      • s[7] = 'b'charIndex['b'] = 1,左指针移动到5,窗口变为"cab",窗口长度为3maxLen保持不变。

    最终结果为3

    1. int lengthOfLongestSubstring(char *s) {
    2. // 使用一个数组来存储每个字符最后出现的位置
    3. int charIndex[128]; // 假设字符集为ASCII,有128个字符
    4. memset(charIndex, -1, sizeof(charIndex)); // 初始化为-1
    5. int left = 0; // 左指针,用于标记窗口的开始位置
    6. int maxLen = 0; // 最长子串的长度
    7. int len = strlen(s);
    8. for (int right = 0; right < len; right++) {
    9. // 如果字符已经在窗口中,并且其位置在左指针之后
    10. if (charIndex[s[right]] >= left) {
    11. // 移动左指针到重复字符的下一个位置
    12. left = charIndex[s[right]] + 1;
    13. }
    14. // 更新每个字符的位置,每个字符初始left都是0
    15. charIndex[s[right]] = right;
    16. // 计算当前窗口的长度.正常是位置,如果该字符已经出现过了,就会更新left,减去的就是上一次出现的位置。
    17. int windowLen = right - left + 1;
    18. // 更新最长子串的长度
    19. if (windowLen > maxLen) {
    20. maxLen = windowLen;
    21. }
    22. }
    23. return maxLen;
    24. }
    • right指针逐个增加,尝试扩大窗口。
    • 检查新加入的字符s[right]是否已经在当前窗口中。
    • 如果已经在窗口中并且其位置在left指针之后,更新left指针的位置。
    • 更新charIndex数组中s[right]字符的位置为right
    • 计算当前窗口的长度windowLen,并与maxLen比较,更新最长子串的长度。

  • 相关阅读:
    开发说这个需求实现不了,怎么破?
    从零开始Blazor Server(10)--编辑角色
    Vue和React对比
    力扣每日一题
    干洗店洗鞋店软件模版,成品系统功能非常完善;
    物联网TCP、UDP、CoAP、LwM2M、MQTT协议简单对比
    【一】ECharts----【基本概念、基本实例】
    玩转 SpringBoot 监控统计(SQL监控、慢SQL记录、Spring监控、去广告)
    Jetson(ubuntu18.04)使用v4l2-ctl工具USB摄像头和CSI 摄像头的规格参数查看方法
    Elasticsearch:从 ES|QL 到 PHP 对象
  • 原文地址:https://blog.csdn.net/m0_61636632/article/details/138013084