【中等】机试-滑动窗口(双指针)-例:无重复字符的最长子串

※高频、重点

字节(飞书)、百度等大厂测开高频面试题:最长不重复子串

. - 力扣(LeetCode)字节飞书面经里的高频题,没做出来,需要好好复习。

重点考察-滑动窗口这个概念,自学记录一下:

一、滑动窗口

滑动窗口本质是双指针。处理连续的 子 字符串/数组,如最长最短等问题。(下图以最长不重复子串为例子)

如上图,核心思想就是满足条件的话,让黑色指针右移动;如果当前条件不满足,白色指针右移动。同时可以记录最长长度。

当黑色指针无法移动时,白色指针移动,白指针移动后如果黑色能移动就移动黑色。同时一个变量记录最大长度。

同时,为了满足这种关系,需要用到set数据结构(不可有重复元素)

此类问题核心代码模板:

/* 滑动窗口算法框架 */
void slidingWindow(string s, string t) {
    unordered_map<char, int> need, window;
    for (char c : t) need[c]++;
    
    int left = 0, right = 0;
    int valid = 0;   //其中 valid 变量表示窗口中满足 need 条件的字符个数,,如果 valid 和 need.size 的大小相同,则说明窗口已满足条件,已经完全覆盖了串 T。

    while (right < s.size()) {
        // c 是将移入窗口的字符
        char c = s[right];
        // 右移窗口
        right++;
        // 进行窗口内数据的一系列更新
        ...

        
        // 判断左侧窗口是否要收缩
        while (window needs shrink) {
            // d 是将移出窗口的字符
            char d = s[left];
            // 左移窗口
            left++;
            // 进行窗口内数据的一系列更新
            ...
        }
    }
}

二、实战

2.1字节(飞书)\百度一面:最长不重复子串-(再练习)

题目链接在开头,做为测开面试常见手撕题,必须要会做。

(0914学习了滑动窗口概念和set用法后才做出来了,需要再练),注意其中的set用法

set<char> ans;//根据类型定义,像vector

ans.count()//检查某个元素是否在set里,1在0不在

ans.insert();//插入元素

ans.erase()//删除某个指定元素

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int max1=0;//最小长度是0,空字符串情况
        int black=0,white=0;
        set<char> ans;

        while(black!=int(s.length())){
            if(!ans.count(s[black])){//如果不存在,存里面,black++
                ans.insert(s[black]);
                black++;
                max1=max(max1,int(ans.size()));
            }else{//存在的话删掉首部的,white++
                ans.erase(s[white]);
                white++;
            }
        }
        return max1;
    }
};
  • 时间复杂度:O(n)      空间复杂度:O(n)

2.2哔哩哔哩:14、牛客:最长无重复子数组

最长无重复子数组_牛客题霸_牛客网 同类题,只不过字符串换成了数组,上面一道能做出来这道题也能做出来

class Solution {
public:
    int maxLength(vector<int>& arr) {
        int black=0,white=0;
        set<int> s;
        int max1=0;
        while(black!=arr.size()){
            if(!s.count(arr[black])){
                s.insert(arr[black]);
                black++;
                max1=max(max1,int(s.size()));
            }else{
                s.erase(arr[white]);
                white++;
            }
        }
        return max1;
    }
};

2.3 力扣上同类高频题:438. 找到字符串中所有字母异位词-不会,回头在练习

 相当于,输入一个串 S,一个串 P,找到 S 中所有 P 的排列,返回它们的起始索引

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        unordered_map<char,int> need,window;
        vector<int> ans;
        for(char c:p){
            need[c]++;
        }

        int left=0,right=0;
        int v=0;

        while(right<int(s.length())){
            char c=s[right];
            right++;

            if(need.count(c)){
                window[c]++;
                if(window[c]==need[c]){
                    v++;
                }
            }

            while(right-left>=int(p.length())){ //left右移,缩框
                if(v==need.size()){
                    ans.push_back(left);
                }

                char d=s[left];
                left++;

                if(need.count(d)){
                    if(window[d]==need[d]){
                        v--;
                    }
                    window[d]--;
                }
            }
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

牛大了202X

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值