【双指针】最长不重复子串

题解:最长不重复子串

题目传送门

点击跳转至题目页面

一、题目重述

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

示例1
输入:“abcabcbb”
输出:3
解释:最长无重复字符子串是"abc",长度为3

示例2
输入:“abcdeff”
输出:6
解释:最长无重复字符子串是"abcdef",长度为6

二、题目分析

本题需要在一个字符串中找到最长的连续子串,该子串中所有字符都不重复。关键在于如何高效地判断和处理重复字符。

三、解题思路

使用**滑动窗口(双指针)**算法:

  1. 维护一个窗口(由左右指针l和r界定)
  2. 使用哈希集合存储当前窗口中的字符
  3. 当遇到重复字符时,移动左指针直到消除重复
  4. 始终保持窗口内无重复字符,并记录最大窗口大小

四、算法讲解

算法原理

滑动窗口算法适用于解决数组/字符串的子区间问题。通过动态调整窗口的左右边界,可以在O(n)时间内解决问题。

使用场景

  • 需要寻找满足条件的连续子区间
  • 通常用于字符串或数组问题
  • 特别适合"最长无重复"这类问题

实现步骤

  1. 初始化左指针l=0和结果ans=0
  2. 右指针r从0开始遍历字符串
  3. 如果当前字符s[r]在集合中:
    • 从集合中移除s[l]
    • 左指针l右移
  4. 将s[r]加入集合
  5. 更新最大长度ans

示例解析

以**“abcabcbb”**为例:

  • 初始:l=0, ans=0
  • r=0(‘a’): 加入集合,ans=1
  • r=1(‘b’): 加入集合,ans=2
  • r=2(‘c’): 加入集合,ans=3
  • r=3(‘a’): 重复,移除s0,l=1
  • r=4(‘b’): 重复,移除s1,l=2
  • 最终ans=3

五、代码实现

#include <bits/stdc++.h>
using namespace std;
string s;

int main()
{
    cin >> s;
    unordered_set<char> st;  // 用于存储当前窗口中的字符
    int l = 0, ans = 0;      // l是左指针,ans记录最大长度
    
    for (int r = 0; r < s.size(); r ++)  // r是右指针,遍历字符串
    {
        // 当发现重复字符时,移动左指针直到消除重复
        while (st.find(s[r]) != st.end())
        {
            st.erase(s[l]);  // 从集合中移除左指针字符
            l ++;            // 左指针右移
        }
        st.insert(s[r]);      // 将当前字符加入集合
        ans = max(ans, r - l + 1);  // 更新最大长度
    }
    cout << ans <<"\n";
    
    return 0;
}

六、代码重点细节解释

  1. unordered_set st:哈希集合,用于O(1)时间判断字符是否存在
  2. 双指针l和r:维护滑动窗口的边界
  3. while循环:处理重复字符的关键,确保窗口内无重复
  4. ans更新:每次扩展右边界后计算当前窗口长度

七、复杂度分析

  • 时间复杂度:O(n),每个字符最多被访问两次(左右指针各一次)
  • 空间复杂度:O(min(m,n)),m是字符集大小,最坏情况存储所有不同字符

八、关键点

  1. 滑动窗口的动态调整
  2. 哈希集合的快速查找
  3. 重复字符的处理方式
  4. 窗口长度的实时计算

九、总结

本题通过滑动窗口算法高效解决了最长无重复子串问题。关键在于:

  • 使用哈希集合快速判断重复
  • 动态调整窗口边界
  • 实时更新最大长度

该算法思路清晰,实现简洁,是处理类似子串问题的经典方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hongjianMa

感恩社区,回馈社区

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值