⭐算法入门⭐《双指针》中等01 —— LeetCode 3. 无重复字符的最长子串

饭不食,水不饮,题必须刷

C语言免费动漫教程,和我一起打卡!
光天化日学C语言

LeetCode 太难?先看简单题!
C语言入门100例

数据结构难?不存在的!
画解数据结构

闭关刷 LeetCode,剑指大厂Offer!
LeetCode 刷题指引

LeetCode 太简单?算法学起来!
夜深人静写算法

文章目录

  • 一、题目
    • 1、题目描述
    • 2、基础框架
    • 3、原题链接
  • 二、解题报告
    • 1、思路分析
    • 2、时间复杂度
    • 3、代码详解
  • 三、本题小知识

一、题目

1、题目描述

  给定一个长度为 n ( 1 ≤ n ≤ 1 0 7 ) n (1 \le n \le 10^7) n(1n107) 的字符串 s s s,求一个最长的满足所有字符不重复的子串的长度。
  样例输入:" a b c a b c b b g abcabcbbg abcabcbbg"
  样例输出: 3 3 3

2、基础框架

  • c++ 版本给出的基础框架代码如下:
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
    }
};
  • 其中 string是 C++ 的 STL 中的模板类,可以用来做字符串的各种操作;

3、原题链接

( 1 ) (1) (1) LeetCode 3. 无重复字符的最长子串
( 2 ) (2) (2) 剑指 Offer II 016. 不含重复字符的最长子字符串
( 3 ) (3) (3) 剑指 Offer 48. 最长不含重复字符的子字符串

二、解题报告

1、思路分析

  • 我们考虑一个子串以 s i s_i si 为左端点, s j s_j sj 为右端点,且 s [ i : j − 1 ] s[i:j-1] s[i:j1] 中不存在重复字符, s [ i : j ] s[i:j] s[i:j] 中存在重复字符(换言之, s j s_j sj s [ i : j − 1 ] s[i:j-1] s[i:j1] 中某个字符相同)。如图所示:
  • 那么我们没必要再去检测 s [ i : j + 1 ] s[i:j+1] s[i:j+1] s [ i : j + 2 ] s[i:j+2] s[i:j+2] s [ i : n − 1 ] s[i:n-1] s[i:n1] 这几个字符串的合法性,因为当前情况 s [ i : j ] s[i:j] s[i:j] 是非法的,而这些字符串是完全包含 s [ i : j ] s[i:j] s[i:j] 的,所以它们必然也是不合法的。
  • 那么我们可以把枚举的左端点自增,即: i = i + 1 i = i +1 i=i+1,这时,按照朴素算法的实现,右端点需要重置,即 j = i j = i j=i,实际上这里的右端点可以不动。
  • 可以这么考虑,由于 s j s_j sj 这个字符和 s [ i : j − 1 ] s[i:j-1] s[i:j1] 中的字符产生了重复,假设这个重复的字符的下标为 k k k,那么 i i i 必须满足 i > k i \gt k i>k,换言之, i i i 可以一直自增,直到 i = k + 1 i = k+1 i=k+1,如图所示:
    在这里插入图片描述
  • 这个问题是 双指针 问题的原题,详细的算法可以参考:夜深人静写算法(二十八)- 尺取法。

2、时间复杂度

  • 两个指针都只会递增各一次,所以时间复杂度为 O ( n ) O(n) O(n)

3、代码详解

class Solution {
    int hash[257];

public:
    int lengthOfLongestSubstring(string s) {
        memset(hash, 0, sizeof(hash));
        int maxLen = 0;
        int i = 0, j = -1;             // (1)
        int len = s.length();          // (2)
        while(j++ < len - 1) {
            ++hash[ s[j] ];            // (3)
            while(hash[ s[j] ] > 1) {  // (4)
                --hash[ s[i] ];        // (5)
                ++i;
            }
            if(j - i + 1 > maxLen) {   // (6)
                maxLen = j - i + 1;
            }
        }
        return maxLen;
    }
};
  • ( 1 ) (1) (1) 代表一开始是空串;
  • ( 2 ) (2) (2) 之所以要这么做,是因为s.length()是无符号整型,当 j == -1的情况为无符号整型的最大值,永远都无法进入下面的while(j++ < len - 1)这个循环;
  • ( 3 ) (3) (3) 尝试向右移动 右指针;
  • ( 4 ) (4) (4) 合法性判定:所有字符个数不超过1;
  • ( 5 ) (5) (5) 尝试向右移动 左指针;
  • ( 6 ) (6) (6) 更新最大合法长度;

三、本题小知识

无符号整型在进行判断的时候,如果赋值为 -1,就有可能导致变成整数最大值导致逻辑错误;


你可能感兴趣的:(《LeetCode算法全集》,算法,数据结构,leetcode,c++,双指针)