力扣热题100——滑动窗口

无重复字符的最长子串

在这里插入图片描述

  • 步骤 1:初始状态
    字符串 s = “abcabcbb”,哈希表 charSet 初始为空,双指针 left = 0,right = 0。
哈希表(charSet): {}  
字符串:          a b c a b c b b  
指针:           ↑  
               left/right  
  • 步骤 2:right = 0(字符 ‘a’)

    操作:charSet.insert(‘a’)
    哈希表存储:{‘a’}(字符 ‘a’ 作为键存入)

哈希表(charSet): {a}  
字符串:          a b c a b c b b  
指针:           ↑   ↑  
               left  right  
  • 步骤 3:right = 1(字符 ‘b’)

    操作:charSet.insert(‘b’)
    哈希表存储:{‘a’, ‘b’}(新增字符 ‘b’)

哈希表(charSet): {a, b}  
字符串:          a b c a b c b b  
指针:           ↑     ↑  
               left    right  
  • 步骤 4:right = 2(字符 ‘c’)

    操作:charSet.insert(‘c’)
    哈希表存储:{‘a’, ‘b’, ‘c’}(新增字符 ‘c’)

哈希表(charSet): {a, b, c}  
字符串:          a b c a b c b b  
指针:           ↑       ↑  
               left      right  
  • 步骤 5:right = 3(字符 ‘a’)

    检查:charSet.count(‘a’) → true(‘a’ 已存在)
    操作:移除 left 指向的字符 ‘a’ → charSet.erase(‘a’),哈希表变为 {‘b’, ‘c’}
    left++(left = 1)重新插入 ‘a’ → charSet.insert(‘a’),哈希表变为 {‘b’, ‘c’, ‘a’}

哈希表(charSet): {b, c, a}  
字符串:          a b c a b c b b  
指针:             ↑       ↑  
                 left      right  
  • 步骤 6:right = 4(字符 ‘b’)

    检查:charSet.count(‘b’) → true(‘b’ 已存在)
    操作:移除 left 指向的字符 ‘b’ → charSet.erase(‘b’),哈希表变为 {‘c’, ‘a’}
    left++(left = 2)重新插入 ‘b’ → charSet.insert(‘b’),哈希表变为 {‘c’, ‘a’, ‘b’}

哈希表(charSet): {c, a, b}  
字符串:          a b c a b c b b  
指针:               ↑       ↑  
                   left      right  
#include <string>       // 引入string头文件,用于处理字符串
#include <unordered_set> // 引入unordered_set头文件,用于快速判断字符是否重复
using namespace std;    // 使用std命名空间,简化代码书写

class Solution {        // 定义Solution类,封装解题方法
public:                 // 公共成员函数,外部可直接调用
    // 函数定义:接收字符串s,返回最长无重复字符子串的长度
    int lengthOfLongestSubstring(string s) {
        
        unordered_set<char> charSet; // 哈希集合,存储当前窗口内的所有字符(用于去重判断)
        int maxLen = 0;              // 记录最长无重复子串的长度,初始为0
        int left = 0;                // 滑动窗口的左边界指针,初始为0
        
        // 右指针right遍历字符串,作为窗口的右边界
        for (int right = 0; right < s.size(); ++right) {
            
            // 若当前字符s[right]已在窗口中(重复),则移动左指针缩小窗口
            // 直到窗口中不再包含s[right]
            while (charSet.count(s[right])) {
                charSet.erase(s[left]); // 移除左指针指向的字符
                left++;                 // 左指针右移,缩小窗口
            }
            
            // 将当前字符加入窗口(此时窗口中无重复字符)
            charSet.insert(s[right]);
            
            // 更新最长长度:取当前窗口长度(right - left + 1)和历史最大值的较大值
            maxLen = max(maxLen, right - left + 1);
        }
        
        // 返回最长无重复子串的长度
        return maxLen;
    }
};

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

在这里插入图片描述

#include <vector>       // 引入vector容器头文件,用于存储结果和字符计数
#include <string>       // 引入string头文件,处理字符串参数
using namespace std;    // 使用std命名空间,简化代码书写

class Solution {        // 定义Solution类,封装解题方法
public:                 // 公共成员函数,外部可直接调用
    // 函数定义:接收两个字符串s和p,返回s中所有p的字母异位词的起始索引
    vector<int> findAnagrams(string s, string p) {
        
        vector<int> res; // 定义结果容器,存储符合条件的起始索引
        
        int sLen = s.size(), pLen = p.size(); // 计算s和p的长度
        
        // 边界判断:若s的长度小于p,不可能存在异位词,直接返回空结果
        if (sLen < pLen) return res;
        
        // 定义两个计数数组(26个元素对应a-z),统计字符出现次数
        vector<int> sCount(26, 0), pCount(26, 0);
        
        // 初始化计数:统计p的所有字符,以及s中前pLen个字符的出现次数
        for (int i = 0; i < pLen; ++i) {
            pCount[p[i] - 'a']++;  // p[i]-'a'将字符转为0-25的索引(如'a'→0,'b'→1)
            sCount[s[i] - 'a']++;  // 同步统计s的初始窗口(0到pLen-1)
        }
        
        // 若初始窗口的字符计数与p相同,说明0是有效的起始索引
        if (sCount == pCount) res.push_back(0);
        
        // 滑动窗口:从pLen位置开始遍历s的剩余字符
        for (int i = pLen; i < sLen; ++i) {
            // 移除窗口左侧的字符(i-pLen是即将滑出窗口的索引)
            sCount[s[i - pLen] - 'a']--;
            // 加入窗口右侧的新字符(当前i位置的字符)
            sCount[s[i] - 'a']++;
            
            // 若当前窗口的字符计数与p相同,记录起始索引(i-pLen+1)
            if (sCount == pCount) res.push_back(i - pLen + 1);
        }
        
        return res; // 返回所有有效起始索引
    }
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值