567. 字符串的排列

作者: 王可尊 | 来源:发表于2019-01-20 00:28 被阅读0次

567. 字符串的排列

问题

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

示例1:

输入: s1 = "ab" s2 = "eidbaooo"
输出: True
解释: s2 包含 s1 的排列之一 ("ba").

示例2:

输入: s1= "ab" s2 = "eidboaoo"
输出: False

注意:

  • 输入的字符串只包含小写字母
  • 两个字符串的长度都在 [1, 10,000] 之间

解法

题目乍一看似乎没什么好办法,暴力遍历总是行得通。但是时间复杂度嘛,嘿嘿。

接下来深挖一下题目,既然是判断s2是否包含s1,那么我们总是可以排除一些明显不满足条件的地方:

  • s1s2为空
  • s2的长度小于s1

接下来,我们假设s2中有s1的排列a,那么这个排列a的长度肯定是s1的长度length,实际上就是判断这两个字符串不管字母顺序是否相同,
判断两个字符串是否相同可以用一个长度为26的数组,遍历第一个,将字母出现的次数记下来,然后遍历另一个字符串将数组中字母出现的次数减小一,当次数减小到-1时,代表不相同,直接返回false。当遍历完仍然没有返回时,那么两个字符串肯定是相同的。
我们可以设置两个指针,一个起始指针start,一个结束指针end,并且有end = start +length - 1。此时,从end指针处往回判断。至于为什么从end处往回走而不是从start处往前走是因为,我们注意到这样一种情况,当end处的字符在数组中出现次数已经减到0时,end处的字符必然不在排列a中,此时,start可以直接跳到end+1处,可以直接过滤掉部分字符。这样也就不用遍历必然失败的场景了。

代码

java实现

class Solution {
    public boolean checkInclusion(String s1, String s2) {
        //  特殊情况直接跳出
        if (s1 == null || s2 == null || s2.length() < s1.length()) {
            return false;
        }
        // 初始化一个数组,将s1的字母出现次数保存在这个数组中去。
        int[] map = new int[26];
        int length = s1.length();
        //遍历s1放入map
        for (int i = 0; i < length; i++) {
            map[s1.charAt(i) - 'a']++;
        }
        //遍历s2,此时注意到这样一个情况,如果s2包含s1,那么s2子串的长度必然等于s1,因此,可以设置两个指针。
        int start = 0, end = length - 1;
        while (end < s2.length()) {
            // 这里是一个注意点,需要注意不能直接用map处理,否则会导致第一次false后,后面的判断全是false
            int[] temp = map.clone();
            while (end >= start) {
                if (temp[s2.charAt(end) - 'a']-- == 0) {
                    break;
                }
                end--;
            }
            //上一层有两种跳出方式,一种break;一种是正确判断完了。需要区分一下。
            if (end < start) {
                //这种是正常判断完成了。直接返回true 
                return true;
            } else {
                //此时注意到这样一种情况,end处必然不能在s2子串中出现。那么start = end+1,end = start+length-1 可以跳过start与end之间的字符,因为这部分字符必然不满足条件。
                start = end + 1;
                end = start + length - 1;
            }
        }
        return false;
    }
}

相关文章

  • 2021.2.10每日一题

    567. 字符串的排列[https://leetcode-cn.com/problems/permutation-...

  • 567. 字符串的排列

    567. 字符串的排列 问题 给定两个字符串 和 ,写一个函数来判断 是否包含 的排列。换句话说,第一个字符串...

  • 567. 字符串的排列

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

  • 567. 字符串的排列

    给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,...

  • 567. 字符串的排列(Python)

    题目 难度:★★★☆☆类型:字符串方法:滑动窗口 力扣链接请移步本题传送门[https://leetcode-cn...

  • 【LeetCode】567. 字符串的排列(滑动窗口)

    简书内代码已上传GitHub:点击我 去GitHub查看代码这道题和 最小覆盖子串 思路基本一样 题目: 给定两个...

  • 迭代算法

    问题 输入一个字符串,给出该字符串所有的排列 问题分析 非常标准的排列问题,不考虑字符串重复的前提下共有n!种排列...

  • LeetCode - 0006 - ZigZag Convers

    题目概要 将字符串按照ZigZag的顺序重新排列,求排列之后的新字符串。 题目链接 ZigZag Conversi...

  • 38:字符串的排列

    题目38:字符串的排列 输入一个字符串,打印出该字符串中字符的所有排列。 举例说明 例如输入字符串abc。则打印出...

  • 字符串的全排列

    字符串的全排列 题目描述: 输入一个字符串,打印出该字符串中字符的所有排列。 例如输入字符串abc,则输出由字符a...

网友评论

    本文标题:567. 字符串的排列

    本文链接:https://www.haomeiwen.com/subject/kjtgdqtx.html