LeetCode 438. Find All Anagrams in a String

问题描述

  • Given a string s and a non-empty string p, find all the start indices of p’s anagrams in s.
    Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.
    The order of output does not matter.
  • Example:

Input:
s: “cbaebabacd” p: “abc”
Output:
[0, 6]
Explanation:
The substring with start index = 0 is “cba”, which is an anagram of “abc”.
The substring with start index = 6 is “bac”, which is an anagram of “abc”.


Input:
s: “abab” p: “ab”
Output:
[0, 1, 2]
Explanation:
The substring with start index = 0 is “ab”, which is an anagram of “ab”.
The substring with start index = 1 is “ba”, which is an anagram of “ab”.
The substring with start index = 2 is “ab”, which is an anagram of “ab”.

问题分析

  • 在s串中找出所有p的 Anagrams子串,用滑动窗口来做。
    滑动窗口的大致流程为起初窗口为[left, right),然后将right处元素满足加入窗口。看加数发生了什么变化,根据变化决定缩小窗口,或者继续扩大窗口。比如该题,若加数后满足形成的子串满足既定的规则,则收集当前窗口的结果。满足一定规则后,right不能继续扩了,则通过右移left来缩小窗口,才能使当前窗口能够重新加数,得到新的子串。直到right遍历到数组末尾,结束。

经验教训

  • 滑动窗口处理子串或者子数组的技巧
  • 相应题目

代码实现

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        if (s == null || p == null) {
            return new ArrayList<Integer>();
        }
        int sLen = s.length();
        int pLen = p.length();
        if (sLen == 0 || pLen == 0 || sLen < pLen) {
            return new ArrayList<Integer>();
        }
        List<Integer> res = new ArrayList<>();
        //map用来记录当前窗口离p串,每个字符相差的个数,若某一字符为负,说明该字符多余了
        int[] map = new int[256];
        //diff用来记录当前窗口离p串还差几个字符,因为初始化窗口不存在数字初始化为pLen,差pLen个字符
        int diff = pLen;
        //因为初始化窗口内不存在数字,那么p的每一个字符都差。
        for (int i = 0; i < pLen; i++) {
            ++map[p.charAt(i)];
        }
        //初始化窗口左右边界,窗口左闭右开,[left, right)
        int left = 0;
        int right = 0;
        while (right < sLen) {
            //窗口加数,更新map
            if (map[s.charAt(right)]-- > 0) {
                //map[s.charAt(right)] > 0 说明待入窗字符属于p串,并且当前窗口内该字符还不满足达到P串的要求
                //若加入该元素,则能改变diff,diff--
                --diff;
            }

            if (diff == 0) {
                //相差字符为0,说明当前窗口满足要求
                res.add(left);
            }
            //如果[left,right)长度已经达到 pLen,说明窗口应该缩小,左侧减数
            if (right - left == pLen) {
                if (map[s.charAt(left)] >= 0){//如果欲出窗的数属于p串,并且并不多余
                    //不多余的元素,出窗一定会影响diff
                    ++diff;
                }
                //更新map
                ++map[s.charAt(left)];
                //出窗,缩小窗口
                ++left;
            }
            //右指针右移
            ++right;
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值