leetcode 无重复字符的最长子串 的C++实现

一、题目描述

官方链接:无重复字符的最长子串

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

示例 1:

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
      请注意,你的答案必须是子串的长度,"pwke" 是一个子序列,不是子串。

二、题目解析

这里用到的主要思想就是滑动窗口

什么是滑动窗口呢?举个栗子!

对于"pwwkew" 来说

1.窗口为空。
2.往后移动,将字符'p'加入窗口。						  	窗口:p 
3.继续往后移动,将字符'w'加入窗口。					  	窗口:pw 
4.下面这个字符是'w',因为'w'已经在窗口内了,
  而要求不能有重复字符,所以窗口往后移动舍弃前面得到的。 	窗口:w 
5.继续往后移动,将字符'k'加入窗口。						窗口:wk 
6.继续往后移动,将字符'e'加入窗口。						窗口:wke 
7.下面这个字符是'w','w'已经在窗口内了,
  所以窗口舍弃前面得到的,将该'w'加入窗口。				窗口:w 

注:当然,不是每次窗口都是舍弃所有旧的元素,开始添加新的元素,比如字符串"abca",当扫描到最后一个字符'a'的时候,此时窗口只要舍弃掉最前面的'a',把新的'a'加进去就可以了,也就是说,窗口由"abc"-->"bca"。

所以滑动窗口就是,每次将符合要求的元素加入到窗口中,并且根据要求的条件,不断地扩大或者移动窗口。

一般是用队列实现滑动窗口比较好,对于不同的题目可以选择不同的数据结构,但个人觉得,滑动窗口就是个天然的队列结构。

那么对于这道题,我们只需要设置一个max,在每次窗口需要滑动的时候,对比窗口大小和max值,及时更新max就好了。

对于上面的例子,就是在第4max=2(更新窗口前先更新max),在第7max=3

三、代码

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        queue<char> q;

        int flag[150],max = 0;
        for (int i = 0; i < 150; i++)
            flag[i] = 0;

        for (int i = 0; i < s.length(); i++) {
            if(flag[s[i]] == 0){ // 如果 flag为0,说明该元素没有在窗口中,那么将该元素加入窗口。
                q.push(s[i]);
                flag[s[i]] = 1; // 加入窗口后,该元素的 flag赋值为1。
            }
            else { // 否则,该元素已经在窗口中了,此时要移动窗口
                // 先更新 max,如果窗口大小大于 max,那么将 max赋值为窗口的大小,如果题目要求输出最长的字串,那么在这里可以将此时的窗口元素保存
                max = max > q.size() ? max : q.size(); 

                // 移动窗口,将重复元素及其前面的元素全部踢出窗口
                while(!q.empty()){
                    if(q.front() == s[i]){
                        q.pop();
                        break;
                    }

                    // 将元素踢出窗口时,该元素的 flag赋值为 0
                    flag[q.front()] = 0;
                    q.pop();
                }

                q.push(s[i]); // 将新的元素加入窗口
            }
        }

        // 更新 max
        max = max > q.size() ? max : q.size();
        
        return max;
    }

};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值