【算法】滑动窗口—找所有字母异位词

"找到字符串中所有字母异位词"的难度为Medium,看一下题目:

给定一个字符串 S 和一个非空字符串 T,找到 S 中所有是 T 的字母异位词的子串,返回这些子串的起始索引。

所谓的字母异位词,其实就是全排列,原题目相当于让你找 S 中所有 T 的排列,并返回它们

的起始索引。

比如输入 S = "cbaebabacd",T = "abc",算法返回 [0,6],因为 S 中有两个子串 "cba" 和 "bac" 是 T 的排列,它们的起始索引是0和6。

直接套模板(看专栏)写代码:

java 复制代码
package SlidingWindow;

import java.util.*;

// leetcode 015 找到字符串中所有字母异位词
public class FHW {

    public List<Integer> findAnagrams(String s, String p) {
        Map<Character, Integer> need = new HashMap<>(); // 记录p中字符出现次数
        Map<Character, Integer> window = new HashMap<>(); // 记录窗口中的相应字符的出现次数
        for (int i = 0; i < p.length(); i++) {
            char key = p.charAt(i);
            need.put(key, need.getOrDefault(key, 0) + 1);
        }
        int left = 0, right = 0, valid = 0; // valid 表示窗口中满足 need 条件的字符个数
        List<Integer> res = new ArrayList<>();
        while (right < s.length()) {
            // c 是将要移入窗口的字符
            char c = s.charAt(right);
            // 右移窗口
            right++;
            // 进行窗口内数据的一系列更新
            if (need.containsKey(c)) {
                window.put(c, window.getOrDefault(c, 0) + 1);
                if (window.getOrDefault(c, 0).equals(need.getOrDefault(c, 0))) { // window[c] == need[c]
                    valid++;
                }
            }

            /*** debug 输出的位置***/
            System.out.println("window:(" + left + ", " + right + ")");
            /*********************/

            // 判断左侧窗口是否要收缩
            while (right - left >= p.length()) { // window need shrink ---窗口需要收缩
                // 当窗口符合条件时,把起始索引加入 res
                if (valid == need.size()) {
                    res.add(left);
                }
                // d 是将要移出窗口的字符
                char d = s.charAt(left);
                // 左移窗口
                left++;
                // 进行窗口内数据的一系列更新
                if (need.containsKey(d)) {
                    if (window.getOrDefault(d, 0).equals(need.getOrDefault(d, 0))) {
                        valid--;
                    }
                    window.put(d, window.getOrDefault(d, 0) - 1);
                }
            }
        return res;
    }

    public static void main(String[] args) {
        FHW fhw = new FHW();
        List<Integer> list = fhw.findAnagrams("abab","ab");
        System.out.println(list);
    }

}

和寻找字符串的排列一样,只是找到一个合法异位词(排列)之后将起始索引加入 res 即可。

相关推荐
KarrySmile1 分钟前
Day8--滑动窗口与双指针--1004. 最大连续1的个数 III,1658. 将 x 减到 0 的最小操作数,3641. 最长半重复子数组
数据结构·算法·双指针·滑动窗口·不定长滑动窗口·最大连续1的个数·最长子数组
zc.ovo5 分钟前
图论水题4
c++·算法·图论
KyollBM10 分钟前
【Luogu】每日一题——Day20. P4366 [Code+#4] 最短路 (图论)
算法·图论
qqxhb11 分钟前
零基础数据结构与算法——第七章:算法实践与工程应用-金融算法
算法·风险评估算法·金融算法·交易策略算法·欺诈检测算法
墩墩同学1 小时前
【LeetCode题解】LeetCode 74. 搜索二维矩阵
算法·leetcode·二分查找
SunnyKriSmile1 小时前
输入10个数并求最大值
c语言·算法
汤永红1 小时前
week2-[循环嵌套]数位和为m倍数的数
c++·算法·信睡奥赛
崎岖Qiu4 小时前
leetcode100.相同的树(递归练习题)
算法·leetcode·二叉树·力扣·递归
No0d1es11 小时前
电子学会青少年软件编程(C/C++)5级等级考试真题试卷(2024年6月)
c语言·c++·算法·青少年编程·电子学会·五级
大阳12312 小时前
线程(基本概念和相关命令)
开发语言·数据结构·经验分享·算法·线程·学习经验