力扣 567. 字符串的排列

一、 题目

在这里插入图片描述

二、 示例

在这里插入图片描述

三、 思路与代码

1. 思路

  • 本题采用滑动窗口算法, 维护的是定长窗口;
  • 定义windows(窗口中字符的计数器)和needs(排列子串字符的计数器);
  • 首先, right 指针移动扩大窗口, 当窗口中的某一字符与needs计数器中的字符匹配(数量也要匹配)时, val++(代表窗口中满足 needs 条件的字符个数)
  • 窗口收缩的时机为:当right - left(窗口字符串的长度)超过了待排列字符串的长度时, 窗口就要进行收缩了;此时, 若val == needs.size() 说明找到了符合的字符串;否则, 进行窗口的收缩(left++, 将字符移出窗口, 且需判断val是否需要更新);

2. 代码

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        // 套用模板, 注意条件的判断
        // 这一题的特色就是 定长窗口的维护, right 移动, left 移动
        // 与76题进行对比
        int left = 0;
        int right = 0;
        unordered_map<char, int> windows, needs;
        for (char c : s1) {
            needs[c]++;
        }
        int val = 0;    // 计数0
        int s_len = s2.size();
        while (right < s_len) {
            // 移动窗口
            char c = s2[right]; // 待移入窗口的字符
            right++;    // 移动指针, 扩大窗口
            if (needs.count(c)) {
                // 如果 needs 序列中(即子串序列) 包含了 字符d
                windows[c]++;
                // 若匹配(满足个数匹配, 才让val++)
                if (windows[c] == needs[c]) {
                    val++;  // 则计数++
                }
            }
            // 更新窗口收缩 | 定长滑动窗口往后移动
            // >= 子串的长度
            while (right - left >= s1.size()) {
                // 若子串的序列长度都不一样,肯定不匹配
                // needs.size 容器中存有键值对的个数
                if (val == needs.size()) {
                    return true;
                } 
                // 待移出窗口的字符
                char d = s2[left];
                left++;
                // 进行窗口内数据的更新
                if (needs.count(d)) {
                    if (windows[d] == needs[d]) {
                        val--;
                    }
                    windows[d]--;
                }
            }
        }
        // 找不到符合条件的子串
        return false;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值