LeetCode:3.无重复字符的最长字串 -- 滑动窗口方法

3.无重复字符的最长子串

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

方法二:滑动窗口

  1. 设置滑动窗口 (left, right]left 指向初始元素的前一位置,right 指向末尾元素。初始值 left=1,right=0
  2. 依次扩大 right 的值来扩大滑动窗口,直到滑动窗口中出现重复的元素。
  3. 一旦子串中出现重复元素,或 right 已经遍历字符串所有内容时,滑动窗口 (left, rigth] 是最长无重复子串,长度为 right - left-1 ,使用 Longest 记录最长无重复子串的最大长度。
  4. 此时,已经得到了以 left 指向的元素为初始位置的无重复子串,left 右移一位,找下一个元素为初始元素的无重复子串。
  5. 一旦左边界越过右边界,则遍历结束。

该方法的主要思想是:假设我们选择字符串中的第 k k k 个字符作为起始位置,并且得到了不包含重复字符的最长子串的结束位置为 r k r_k rk。那么当我们选择第 k + 1 k+1 k+1 个字符作为起始位置时,首先从 k + 1 k+1 k+1 r k r_k rk 的字符显然是不重复的,并且由于少了原本的第 k k k 个字符,我们可以尝试继续增大 r k r_k rk,直到右侧出现了重复字符为止。

判断重复字符

使用 unordered_set 来判断 是否有重复字符,便于判断哈希集合中是否存在某字符。

代码实现
int lengthOfLongestSubstring(string s) {
    //使用 哈希集合,记录每个字符是否出现过
    unordered_set<char> ItemOfSub;
    int nSize = s.size();
    int Longest = 0;    //记录最长子串的长度

    //设置滑动窗口的左右边界,left指向初始元素的前一位置,right指向末尾元素
    int left = -1, right = 0;

    while (left < right) {
      //遍历的第一步时,集合中没有元素,此时 left 指向 -1,不需要删除元素
      if (left >= 0) {
        ItemOfSub.erase(s[left]);
      }
      while (right < nSize && ItemOfSub.count(s[right]) == 0) {
        //子串中不包含 右指针 指向的元素
        ItemOfSub.insert(s[right]);
        right++;
      }
      
      //一旦子串中出现重复元素,或 right 已经遍历字符串所有内容
      //(left, rigth]是最长无重复子串,长度为right - left-1
      Longest = max(Longest, right - left-1);

      //此时,已经得到了以 left 指向的元素为初始位置的无重复子串
      //left 右移一位,找下一个元素为初始元素的无重复子串
      left++;
    }
    return Longest;
  }

时间复杂度: O ( N ) O(N ) O(N) N N N 是字符串的长度。

空间复杂度: O ( ∣ Σ ∣ ) O(|\Sigma|) O(Σ) Σ \Sigma Σ 表示字符集,即字符串中可以出现的字符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值