labuladong日常刷题-滑动窗口 | LeetCode 3无重复字符的最长子串 438找到字符串中所有字母异位词 567字符串的排列 76最小覆盖子串 | 花式遍历 54螺旋矩阵

滑动窗口–双指针、快慢指针的加难版

LeetCode 3 无重复字符的最长子串 2024.1.3

int lengthOfLongestSubstring(string s) {
    //length记录最长子串长度
    int length = 0;
    //窗口的左侧索引
    int left = 0;
    //遍历
    for(int i = 0; i < s.size(); i++)
    {
        //当遍历元素出现在窗口内时
        if(find(s.begin()+left, s.end(), s[i])-s.begin() != i)
        {
            //更新最大窗口大小
            length = length < i - left ? i-left : length;
            //更新左侧窗口为遍历元素上一次出现位置的向右一个
            left = find(s.begin()+left, s.end(), s[i])-s.begin() + 1;
            continue;
        }
    }
    //最后需要再更新一次最长子串长度
    length = length < s.size() - left ? s.size()-left : length;
    return length;
}

LeetCode 438 找到字符串中所有字母异位词 2024.1.6

vector<int> findAnagrams(string s, string p) {
    //result数组存放答案索引
    vector<int> result;
    //用哈希表记录p字符串中元素及个数和窗口内元素及个数
    unordered_map<char, int> need,window;
    //统计p字符串中元素及个数
    for(char c : p)
        need[c]++;
    //窗口边界,左闭右开
    int left = 0, right = 0;
    //sym变量记录窗口内达到p字符串中某种元素个数的元素种数
    int sym = 0;
    //当右边界未到数组右边界时遍历
    while(right < s.size())
    {
        //记录当前right元素
        char tempadd = s[right];
        //右边界向右移动
        right++;
        //如果p字符串中有tempadd元素
        if(need.count(tempadd))
        {
            //那么窗口内的tempadd元素个数增加
            window[tempadd]++;
            //当窗口内tempadd元素个数等于p字符串中需要tempadd元素个数时,sym++
            if(window[tempadd] == need[tempadd])
                sym++;
        }
        //当窗口大小大于等于p字符串长度时,需要减小窗口大小
        while(right-left >= p.size())
        {
            //当窗口大小等于p字符串长度时,判断sym是否等于p字符串中元素种数
            //当等于时,说明窗口中字符串是异位词的子串,将left加入到result中
            if(sym == need.size())
                result.push_back(left);
            //记录窗口左侧元素,将要被删除的元素
            char tempcut = s[left];
            //左侧边界向右,left++
            left++;
            //如果删除的元素是p字符串中需要的,那么需要判断和操作
            if(need.count(tempcut))
            {
                //判断如果窗口中该元素个数是否满足p字符串中需要
                //如果需要,那么删除后,满足p字符串的元素种数减1
                if(window[tempcut] == need[tempcut])
                    sym--;
                //窗口中该元素个数减1
                window[tempcut]--;
            }
        }
    }
    return result;
}

LeetCode 567 字符串的排列 2024.1.6

bool checkInclusion(string s1, string s2) {
    //滑动窗口,基本与438题相同
    //用哈希表记录s1字符串中元素及个数和窗口内元素及个数
    unordered_map<char, int> need, window;
     //sym变量记录窗口内达到s1字符串中某种元素个数的元素种数
    int sym = 0;
    //窗口边界,左闭右开
    int left = 0, right = 0;
    //统计p字符串中元素及个数
    for(char c : s1)
        need[c]++;
    //当右边界未到数组右边界时遍历
    while(right < s2.size())
    {
        //记录当前right元素
        char tempadd = s2[right];
        //右边界向右移动
        right++;
        //如果s1字符串中有tempadd元素
        if(need.count(tempadd))
        {
            //那么窗口内的tempadd元素个数增加
            window[tempadd]++;
            //当窗口内tempadd元素个数等于s1字符串中需要tempadd元素个数时,sym++
            if(window[tempadd] == need[tempadd])
                sym++;
        }
        //当窗口大小大于等于p字符串长度时,需要减小窗口大小
        if(right-left >= s1.size())
        {
            //记录窗口左侧元素,将要被删除的元素
            char tempcut = s2[left];
            //左侧边界向右,left++
            left++;
            //当窗口大小等于s1字符串长度时,判断sym是否等于s1字符串中元素种数
            //当等于时,说明窗口中字符串是异位词的子串,直接返回true
            if(sym == need.size())
                return true;
            //如果删除的元素是s1字符串中需要的,那么需要判断和操作
            if(need.count(tempcut))
            {
                //判断如果窗口中该元素个数是否满足s1字符串中需要
                //如果需要,那么删除后,满足s1字符串的元素种数减1
                if(need[tempcut] == window[tempcut])
                    sym--;
                //窗口中该元素个数减1
                window[tempcut]--;
            }
        }
    }
    return false;
}

LeetCode 76 最小覆盖子串 2024.1.6

string minWindow(string s, string t) {
    //滑动窗口
    //用哈希表记录t字符串中元素及个数和窗口内元素及个数
    unordered_map<char, int> need, window;
    //窗口边界,左闭右开
    int left = 0, right = 0;
    //sym变量记录窗口内达到s1字符串中某种元素个数的元素种数
    //start记录满足条件的最小子串的初始索引
    //minlength记录最小子串的长度,默认为最大值
    int start = 0, sym = 0, minlength = INT_MAX;
    //统计t字符串中元素及个数
    for(char c : t)
        need[c]++;
    //当右边界未到数组右边界时遍历
    while(right < s.size())
    {
        //记录当前right元素
        char tempadd = s[right];
        //右边界向右移动
        right++;
        //如果t字符串中有tempadd元素
        if(need.count(tempadd))
        {
            //那么窗口内的tempadd元素个数增加
            window[tempadd]++;
            //当窗口内tempadd元素个数等于t字符串中需要tempadd元素个数时,sym++
            if(window[tempadd] == need[tempadd])
                sym++;
        }
        //当窗口中元素种数>=t字符串中元素种类时
        while(left < s.size() && sym >= need.size())
        {
            //如果当前满足条件的窗口的宽度小于记录的最小子串的长度,
            //那么更新最小子串的开始索引和长度
            //注意这里不要一直s.substr(pos, len),本题中内存爆了
            if(right-left <= minlength)
            {
                start = left;
                minlength = right-left;
            }
            //记录窗口左侧元素,将要被删除的元素
            char tempcut = s[left];
            //左侧边界向右,left++
            left++;
            //如果删除的元素是t字符串中需要的,那么需要判断和操作
            if(need.count(tempcut))
            {
                //判断如果窗口中该元素个数是否满足s1字符串中需要
                //如果需要,那么删除后,满足s1字符串的元素种数减1
                if(need[tempcut] == window[tempcut])
                    sym--;
                 //窗口中该元素个数减1
                window[tempcut]--;
            }
        }
    }
    //判断minlength是否为初始值,如果时则返回空字符串,否则返回最小子串
    return minlength == INT_MAX ? "" : s.substr(start, minlength);
}

花式遍历数组

LeetCode 54 螺旋矩阵 2024.1.2

  • 题目链接

  • labuladong讲解
    在这里插入图片描述

  • 题意:第59题是将元素输入到nXn二维数组中,可以左闭右开,也可以左闭右闭;该题存在mXn大小矩阵,不一定能绕整圈,所以左闭右闭更好,不用考虑绕不了整圈的边界条件

vector<int> spiralOrder(vector<vector<int>>& matrix) {
    //创建要返回的数组
    vector<int> result;
    //记录被遍历的二维数组的行数与列数
    int m = matrix.size();
    int n = matrix[0].size();
    //记录遍历时上下左右边界
    int up = 0, down = m-1, left = 0, right = n-1;
    //当输出数组中元素个数不够时循环
    while (result.size() < m*n)
    {
        // 因为要向右移动,所以保证上下边界内有元素
        if(up <= down)
        {
        	//遍历一整边,左闭右闭
            for (int j = left; j <= right; j++)
            {
                result.push_back(matrix[up][j]);
            }
            //上边界下移
            up++;
        }
        // 因为要向下移动,所以保证左右边界内有元素
        if(left <= right)
        {
        	for (int i = up; i <= down; i++)
        	{
        		result.push_back(matrix[i][right]);
        	}
        	//右边界左移
        	right--;
        }
        // 因为要向左移动,所以保证上下边界内有元素
        if(up <= down)
        {
        	for (int j = right; j >= left; j--)
        	{
        		result.push_back(matrix[down][j]);
        	}
        	//下边界上移
        	down--;
        }
        // 因为要向上移动,所以保证左右边界内有元素
        if(left <= right)
        {
        	for (int i = down; i >= up; i--)
        	{
        		result.push_back(matrix[i][left]);
        	}
            //左边界右移
            left++;
        }
    }
    return result;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值