小工具知识网

当前位置: 首页 > 行业知识 > 【力扣】无重复字符的最长子串,滑动窗口 + 哈希集合

行业知识

【力扣】无重复字符的最长子串,滑动窗口 + 哈希集合

2026-11-01 12:26:14 来源:互联网转载

���重复字符的最长子串原题地址

()

方法一:滑动窗口(双指针) + 哈希集合

考虑找出字符串s的所有的无重复字符的子串,求出这些子串长度的最大值即可。

使用下标 [left,right] 来维护子串。我们只需要找到每一个 left 对应的所有 right 即可,换句话说,固定了 left 之后,我们让 right 从 left 的位置开始,向后滑动,直到 [left,right] 出现重复字符为止。

()

以下为所有无重复字符的子串:

(a) b c a b c b b(a b) c a b c b b(a b c) a b c b ba (b) c a b c b ba (b c) a b c b ba (b c a) b c b ba b (c) a b c b ba b (c a) b c b ba b (c a b) c b ba b c (a) b c b ba b c (a b) c b ba b c (a b c) b ba b c a (b) c b ba b c a (b c) b ba b c a b (c) b ba b c a b (c b) ba b c a b c (b) ba b c a b c b (b)

由于我们要找的是这些子串中最长的那个,所以固定 left 后,先让 right 右移至出现重复字符或者 right 移动到字符串的末尾,再统计该子串的长度,即 right-left+1 ,求出其中的最大值即可。

需要统计如下子串的长度:

(a b c) a b c b ba (b c a) b c b ba b (c a b) c b ba b c (a b c) b ba b c a (b c) b ba b c a b (c b) ba b c a b c (b) ba b c a b c b (b)

显然,当某条子串 [left,right] 的右端点 right 已经到达字符串的末尾时,若 left 继续右移,只会缩短子串长度,所以此时无需继续统计。

为了判断子串是否已经出现重复字符,可以利用哈希集合(如 C++ 中的 unordered_set ),来存储 [left,right] 中的所有字符,当 right 右移时,就把最右边的字符添加到哈希集合中;当 left 右移时,就把最左边的字符从哈希集合中删除。这样,每次只需判断子串新增加的字符是否已经在哈希集合中出现过即可。

// 方法一:滑动窗口class Solution{public:    int lengthOfLongestSubstring(string s)    {        if (s.empty())        {            return 0;        }        unordered_set us;        int ans = 0;        // [left,right] 表示子串        int left = 0, right = 0;        us.insert(s[0]);        while (1)        {            // 右指针右移,直到出现重复字符            while (right + 1  

方法二:对方法一的优化,实现左指针 left 的快速跳转

方法一是固定 left ,让 right 尽可能右移,从而统计所有的 [left,right] 区间长度 right-left+1 的最大值,这样最坏情况下 left 会遍历完整个字符串。

考虑用 key-value 模型的哈希表(如 C++ 中的 unordered_set ),每次把 [0,right] 的字符及其对应下标都存进去。

我们用 right 遍历字符串,若 right 右移后指向的字符在哈希表中出现过,且最后出现的下标在 [left,right] 的范围内,说明此时的子串 [left,right] 已经出现了重复字符,此时 left 应该跳转到 s[right] 最后一次出现的位置的后面。

下面的例子中, right 本来指向 f ,右移后指向 c , left 就要从 a 直接跳转到第一个 c 后面,否则 [left,right] 会出现重复字符。

(a b c d e f) ca b c (d e f c)

每次 right 右移后,都要把 s[right] 及对应的下标 right 都存储到哈希表中,也就是把 s[right] 当前最后出现的位置存储到哈希表中。

// 方法二:滑动窗口优化class Solution{public:    int lengthOfLongestSubstring(string s)    {        if (s.size() second + 1);            }            // 子串长度为 right-left+1            ans = max(ans, right - left + 1);            um[s[right]] = right;        }        return ans;    }};

上一篇:揭秘协商速率,达成快速共识的关键所在

下一篇:揭秘鹦鹉鱼变白真相,疾病、水质影响还是另有原因?