LCR 014

题目LCR 014


解法一:滑动窗口

使用两个长度26的int数组,分别记录s1s2子数组中各个字符出现的次数。滑动窗口每次移动后,通过Arrays.equals()来确定数组内容是否相等。

    public boolean checkInclusion(String s1, String s2) {
        if (s1.length() > s2.length()) return false;
        int[] arr1 = new int[26];
        int[] arr2 = new int[26];
        for (int i = 0; i < s1.length(); i++) {
            arr1[s1.charAt(i) - 'a']++;
            arr2[s2.charAt(i) - 'a']++;
        }
        if (Arrays.equals(arr1, arr2)) return true;
        for (int i = s1.length(); i < s2.length(); i++) {
            arr2[s2.charAt(i) - 'a']++;
            arr2[s2.charAt(i - s1.length()) - 'a']--;
            if (Arrays.equals(arr1, arr2)) return true;
        }
        return false;
    }

注意

  • Arrays.equals效率低,需要一个个元素进行比较

  • 变位词只会将字符位置变换,字符个数依然不变


解法二:滑动窗口优化

创建一个长度26的int数组,用来记录两个自符串中各个字符不同的个数,再维护一个diff变量用来记录两个字符串中不同字符的个数。

    public boolean checkInclusion2(String s1, String s2) {
        int diff = 0;
        if (s1.length() > s2.length()) return false;
        int[] arr = new int[26];
        for (int i = 0; i < s1.length(); i++) {
            arr[s1.charAt(i) - 'a']++;
            arr[s2.charAt(i) - 'a']--;
        }
        for (int i : arr) {
            if (i != 0) diff++;
        }
        if (diff == 0) return true;
        for (int i = s1.length(); i < s2.length(); i++) {
            int x = s2.charAt(i) - 'a', y = s2.charAt(i - s1.length()) - 'a';
            //重点------
            if (x == y) continue;
            if (arr[x] == 0) diff++;
            arr[x]--;
            if (arr[x] == 0) diff--;
            if (arr[y] == 0) diff++;
            arr[y]++;
            if (arr[y] == 0) diff--;
            //重点------
            if (diff == 0) return true;
        }
        return false;
    }

解法三:双指针

该解法最简单,但是循环内部判断逻辑较为。首先创建两个前后指针,前指针指向子数组起始位置,后指针指向子数组结束位置。后指针向后遍历,当s2子数组中的某个字符出现次数大于s1中该字符出现次数,且该子数组长度还没有达到s1的长度时,前指针向右移动,直到该字符出现次数和s1中该字符出现相等,即arr[index] = 0

    public boolean checkInclusion3(String s1, String s2) {
        if (s1.length() > s2.length()) return false;
        int[] arr = new int[26];
        for (int i = 0; i < s1.length(); i++) {
            arr[s1.charAt(i) - 'a']++;
        }
        int left = 0;
        for (int right = 0; right < s2.length(); right++) {
            int index = s2.charAt(right) - 'a';
            arr[index]--;
            while (arr[index] < 0) {
                arr[s2.charAt(left) - 'a']++;
                left++;
            }
            if (right - left + 1 == s1.length()) return true;
        }
        return false;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值