检测子串排列(滑动窗口)

力扣567:字符串的排列

给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的子串。

示例1:
输入: s1 = “ab” s2 = “eidbaooo”
输出: True
解释: s2 包含 s1 的排列之一 (“ba”).

思路1:暴力检测

写过一个根据输入的字符串输出其中字符的全部排列的函数。可以先生成全部的排列,然后在一个一个的对比,但是显然这种方法会非常的慢,我们可以构思简单一点的方法。

思路2:窗口+哈希表

由于只需要检测s2的子串是否是s1的某种排列,所以只需要生成记录字母频率的哈希表,只要哈希表相同,那么就说明可以生成一种排列与之匹配。再结合专题中字母哈希的方法和题目中只有小写字母的特点,可以用一个长度为26的数组作为哈希表。

思路3:窗口更新优化

比起每次窗口滑动都创建一个哈希表,我们可以在滑动的同时更新哈希表。在窗口滑动的同时,更新两端字母的频率即可。这样可以进一步优化时间复杂度。

class Solution {
    public boolean checkInclusion(String s1, String s2) {

        int len1 = s1.length();
        int len2 = s2.length();

        int[] hashS1 = toHash(s1,0,len1);
        int[] hashS2 = new int[26];

        for(int i=0;i+len1<=len2;i++) {
            if(i == 0) {
                hashS2 = toHash(s2,0,len1);
            }
            else {
                hashS2[s2.charAt(i-1)-'a']--;
                hashS2[s2.charAt(i+len1-1)-'a']++;
            }
            boolean flag = true;
            for(int j=0;j<26;j++) {
                if(hashS1[j] != hashS2[j]) flag = false;
            }
            if(flag) return true;

        }

        return false;

    }

    /**
     * @param s 需要转变的字符串
     * @param begin 子串开始的位置
     * @param end 子串结束的位置的后一个位置
     * @return
     */
    public int[] toHash(String s, int begin, int end) {

        int[] hash = new int[26];
        String str = s.substring(begin, end);

        for(int i=0;i<str.length();i++) {
            hash[str.charAt(i) - 'a']++;
        }

        return hash;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值