题目大意:
字符串的排列
给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的子串。
示例1:
输入: s1 = "ab" s2 = "eidbaooo" 输出: True 解释: s2 包含 s1 的排列之一 ("ba").
示例2:
输入: s1= "ab" s2 = "eidboaoo" 输出: False
注意:
- 输入的字符串只包含小写字母
- 两个字符串的长度都在 [1, 10,000] 之间
如果想查看本题目是哪家公司的面试题,请参考以下免费链接: https://leetcode.jp/problemdetail.php?id=567
解题思路分析:
如果s1的任意一种排列是s2的一个子串,那么说明s1中每种字母的个数要与s2某个子串所有字母个数完全相同,因此,本题首先要统计出s1中所包含的每种字母数量,将其保存在数组count中。然后使用双指针方式来遍历s2,起始时,左右两指针均在第0位。利用右指针不断加一来查看当前字符,在count数组中,当前字符的数量减一。减一操作后,如果count的值为0,说明当前字符消耗掉了所有s1中的当前字符,这时查看一下左右区间的长度,如果该长度等于s1的长度,那么说明当前区间可以匹配上s1,直接返回true。如果count值为-1,说明当前字符不存在于s1中,或者当前区间内的当前字符数量多于s1中的数量,此时向右逐步移动左指针,左指针经过的位置表示已经移出区间,此时在count数组中要对相应的字符个数加一,直到出现左指针与右指针指向了相同的字符为止,右指针所指的字符个数count由-1变为0,接下来继续移动右指针,重复上述操作。
实现代码:
public boolean checkInclusion(String s1, String s2) { // 统计s1中所有字母数量 int[] count = new int[26]; for(int i=0;i<s1.length();i++){ count[s1.charAt(i)-'a']++; } // 定义左右指针 int left=0, right=0; while(left<s2.length()&&right<s2.length()){ // 当前字符 int c = s2.charAt(right)-'a'; // 当前字符数量减一 count[c]--; // 如果当前数量为0 if(count[c] == 0){ // 区间长度正好等于s1长度时,说明完全匹配,返回true if(right-left+1==s1.length()) return true; }else if(count[c]<0){ // 如果当前数量小于0 // 移动左指针 while(left<=right){ // 左指针字符 int leftChar = s2.charAt(left++)-'a'; // 左指针字符数量加一 count[leftChar]++; // 左右指针字符相同时,结束移动左指针 if(leftChar==c){ break; } } } right++; // 右指针加一 } return false; }
本题解法执行时间为5ms。
Runtime: 5 ms, faster than 80.89% of Java online submissions for Permutation in String.
Memory Usage: 37.3 MB, less than 88.46% of Java online submissions for Permutation in String.
本网站文章均为原创内容,并可随意转载,但请标明本文链接如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: https://leetcode.jp/leetcode-567-permutation-in-string-解题思路分析/