leetcode567字符串的排列
给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。
换句话说,第一个字符串的排列之一是第二个字符串的子串。
示例1:
输入: s1 = “ab” s2 = “eidbaooo”
输出: True
解释: s2 包含 s1 的排列之一 (“ba”).
示例2:
输入: s1= “ab” s2 = “eidboaoo”
输出: False
我第一次做的时候比较字符串暴力超时了,后来看到题解说可以用map映射做。
具体思路:两个映射分别代表s1的窗口和s2的窗口,用长度为26的数组表示。
每次移动窗口之后,只需要比较s2的数组是不是完全与s1的数组一样就行。而移动窗口也意味着左窗口对应的数字减一(s2Map[s2.charAt(i)-97]–),右窗口加一(s2Map[s2.charAt(i+s1.length())-97]++).
public boolean checkInclusion(String s1, String s2) {
if (s1.length() > s2.length())
return false;
int[] s1Map=new int[26];
int[] s2Map=new int[26];
for(int i=0;i<s1.length();i++) {
s1Map[s1.charAt(i)-97]++;
s2Map[s2.charAt(i)-97]++;
}
for(int i=0;i<s2.length()-s1.length();i++) {
if(judge(s1Map,s2Map))
return true;
s2Map[s2.charAt(i)-97]--;
s2Map[s2.charAt(i+s1.length())-97]++;
}
return judge(s1Map,s2Map);
}
public boolean judge(int[] map1,int[] map2) {
for(int i=0;i<map1.length;i++) {
if(map1[i]!=map2[i])
return false;
}
return true;
}
但是这种方式多开辟了一个数组。还可以只用一个数组。
优化版
只用一个数组index,在创建的时候可以做一些手脚。将s1中的每个字母在对应的位置上减一,对于s2来说,把字母对应值加一。这样就可以正负抵消,最后如果index全都是0,那么就说明存在这样的一个串。
public boolean checkInclusion(String s1, String s2) {
if (s1.length() > s2.length())
return false;
int[] index=new int[26];
for(int i=0;i<s1.length();i++) {
index[s1.charAt(i)-'a']--;
index[s2.charAt(i)-'a']++;
}
if(judge(index))return true;
for(int j=0;j<s2.length()-s1.length();j++) {
index[s2.charAt(j)-'a']--;
index[s2.charAt(j+s1.length())-'a']++;
if(judge(index))return true;
}
return false;
}
public boolean judge(int[] index) {
for(int i=0;i<index.length;i++) {
if(index[i]!=0)
return false;
}
return true;
}
后记:做这道题我第一反应是觉得有什么快速简单的方法,觉得肯定不是暴力破解。结果想了半个多小时,最后没辙还是用暴力破解提交的,而且还超时。给我的教训就是:有的时候可能没有那么多捷径,真的就是暴力破解(或者有捷径我也想不出来_(:τ」∠)_ )。
leetcode 4/100