其他分享
首页 > 其他分享> > 力扣-3-无重复字符的最长字串

力扣-3-无重复字符的最长字串

作者:互联网

做之前看题目的印象是“动态规划”,因为好像和以前做的“最大子数和”看起来有点像

查看标签有“滑动窗口”,这个见过听过,但是不知道具体是什么,但是有印象,计网里的拥塞控制也用到了“滑动窗口”的概念

感觉题目降低难度了,只是要求返回长度不是要求返回子串

有了计网“滑动窗口”的概念,我想是需要两个指针来表示窗口的,头指针表示窗口起始,尾指针表示窗口末尾。另外拿一个变量来记录窗口长度

感觉难点在于:

  1. 如何高效地判重
    我想起了刚刚做的题,用set,如果把字串中的字符放到set中,然后用count函数来判断

那么,试试吧

    int lengthOfLongestSubstring(string s) {
        set<char> st;
        int begin = 0,ret =0;
        for(int end = begin;end<s.size();++end){
            if(st.count(s[end])==0){
                // set中没有该字符,说明没有重复
                st.emplace(s[end]);// 放进去
            }else{
                // set中存在,有重复字符了
                ret = max(ret,end-begin);
                begin = end;// 刷新窗口
            }
        }
        return ret;
    }

第一版,三个示例通过了就迫不及待地提交,结果空字符就报错了
检查一遍健壮性

随手编了一个测试用例,发现一个问题:刷新窗口后set没清空

但还是不对,这是为什么?
问题应该出在最后遍历完成后没有再记录窗口长度,也就是说如果最长无重复子串在数组最后的情况
分析一下,遍历结束后,end指针应该在数组末尾,begin指针还在窗口开头
我把end改成类变量

有一个很复杂的问题,每次出现了重复字符不是把头指针与尾指针置通,而是头指针指向被重复字符的位置去,那我改map,刷新begin到被重复元素的后一个位置,然后这样又有了新问题,容器不能简单得清空了

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int ret = 0;
        if(s==""){
            return ret;
        }
        map<char,int> mp;
        int begin = 0,end;
        for(end = begin;end<s.size();++end){
            if(mp.count(s[end])==1){
                // set中存在,有重复字符了
                int newLocation = mp.at(s[end])+1;
                // 把begin到被重复字符之间的全踢掉      
                for(int i =begin;i<newLocation;++i){
                    mp.erase(s[i]);
                }
                begin = newLocation;// 刷新窗口
                //放到被重复的字符位置去
            }
            // set中没有该字符,说明没有重复
            mp.emplace(s[end],end);// 放进去
            ret = max(ret,end-begin+1);
        }
        return ret;
    }
};

这一版,能把目前的四个用例全部跑过

通过!

标签:字符,begin,end,int,力扣,字串,窗口,指针
来源: https://www.cnblogs.com/yaocy/p/16329023.html