• LeetCode 438. 找到字符串中所有字母异位词__滑动窗口


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

    给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

    异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。

    示例 1:
    
    输入: s = "cbaebabacd", p = "abc"
    输出: [0,6]
    解释:
    起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
    起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
     示例 2:
    
    输入: s = "abab", p = "ab"
    输出: [0,1,2]
    解释:
    起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
    起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
    起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。
     
    
    提示:
    
    1 <= s.length, p.length <= 3 * 104
    s 和 p 仅包含小写字母
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Solution1(直白滑窗):

    显然这题我们可以使用滑动窗口来解决,即直接维护p字符串长度的窗口,每当窗口满时就判断一下窗口内的各种字母数量是否和p的一致即可。

    Code1:

    class Solution {
        public List<Integer> findAnagrams(String s, String p) {
            int[] hash = new int[26];
            int winLen = p.length();
            for(int i=0;i<winLen;i++){
                char c = p.charAt(i);
                hash[c - 'a']++;
            }
    
            List<Integer> res = new ArrayList<>();
            List<Integer> window = new ArrayList<>();
            for(int i=0;i<s.length();i++){
                char c = s.charAt(i);
                if(window.size() < winLen){
                    window.add(i);
                }
                else{
                    check(res,winLen,window,hash,s);
                    window.remove((int)0);
                    i--;
                }
            }
            if(window.size() < winLen){
                return res;
            }
            check(res,winLen,window,hash,s);
            return res;
        }
    
        public void check(List<Integer> res,int winLen,List<Integer> window,int[] hash,String s){
            int[] hashTemp = new int[26];
            for(int k=0;k<winLen;k++){
                Integer index = window.get(k);
                hashTemp[s.charAt(index) - 'a']++;
            }
            int j = 0;
            for(;j<26;j++){
                if(hash[j] != hashTemp[j])
                    break;
            }
            if(j == 26){
                res.add(window.get(0));
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    Solution2(优化便捷滑窗):

    我们可以不直接维护普通滑窗,因为我们发现上述方法一,由于是维护一个有序序列来模拟滑窗,后面还需要一个哈希数组来表示滑窗内含有的字母种类及数量,因此我们可以想只创建一次哈希数组即可,在滑窗滑出老元素和滑进新元素时直接在那一个哈希数组上进行修改就行。
    接着我们发现,可以直接使用哈希数组代替滑窗的有序序列进行存储,只用两个下标来模拟滑窗即可,滑窗本身不需要存储内容,交给哈希数组存储即可。

    Code2:

    class Solution {
        public List<Integer> findAnagrams(String s, String p) {
            int slen = s.length();
            int plen = p.length();
    
            List<Integer> res = new ArrayList<>();
            if(s.length() < p.length()){
                return res;
            }
            
            int[] hash = new int[26];
            int[] hashTemp = new int[26];
            // 先给滑窗塞满
            for(int i=0;i<plen;i++){
                hash[p.charAt(i) - 'a']++;
                hashTemp[s.charAt(i) - 'a']++;
            }
    
            if(Arrays.equals(hash,hashTemp)){
                res.add(0);
            }
    
    		// 维护滑窗的两个下标即可,一个头部,一个头部+滑窗长度即可
            for(int i=0;i<slen - plen ;i++){
                hashTemp[s.charAt(i) - 'a']--;
                hashTemp[s.charAt(i + plen) - 'a']++;
                if(Arrays.equals(hash,hashTemp)){
                    res.add(i+1);
                }
            }
    
            return res;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
  • 相关阅读:
    java基于Springboot+vue的旅游景点酒店预定管理系统 element
    第十五届蓝桥杯模拟赛【第三期】Java
    Vue3 源码阅读(5):响应式系统 —— Vue2 中的 watch 和 computed
    意外发现腾讯T4手码《SpringMVC源码解析》,如获至宝,果断收藏
    外贸软件出口管理亮点有哪些,出口贸易过程全解析
    自动化测试Selenium(二)
    线程等待唤醒几种方法
    rem 实现自应用屏幕大小
    建造者模式
    Docker开放远程安全访问(开启2376端口和CA认证)
  • 原文地址:https://blog.csdn.net/xiangguang_fight/article/details/125470355