思路一:
- A[]用来表明有哪些字母出现在s1中,出现了几次。无需记录字母的位置,因为题目中要求的是任意排列,只需记录次数。
- System.arraycopy函数是深拷贝,将A[]的内容拷贝给B[]。
- B[]减去s2中出现的字母及其次数,一旦出现不属于s1的字母,那么当前子串不满足条件,进入下一个子串,(!)要再次copy完整的A[]给B[]。出现属于s1的字母,就减1。
- 如果B[]和C[]相等,C[]为全0数组,说明s2中含有s1中所有字母的一个排列,返回true。
代码java:
class Solution {
public boolean checkInclusion(String s1, String s2) {
int[] A = new int[128];
for (int i = 0; i < s1.length(); i++) {
int value = Integer.valueOf(s1.charAt(i));
A[value]++;
}
int[] B = new int[128];
int[] C = new int[128];//全0的数组,用于比较
for (int i = 0; i < s2.length(); i++) {
System.arraycopy(A, 0, B, 0, A.length);
for(int j=i;j<s2.length();j++) {
if(B[Integer.valueOf(s2.charAt(j))] == 0) {//子串中出现不属于s1的字母,直接退出
break;
}
B[Integer.valueOf(s2.charAt(j))]--;
}
if (Arrays.equals(B, C)) {
return true;
}
}
return false;
}
}
思路二:
- 根据大佬的c++代码写的。在c++中有vector类型,比较起来更加方便,java中我用数组代替。
- 两个数组arr1[],arr2[]也是用来记录s1,s2中出现的字母及其次数。首先,先比较s2中前len1个字母组成的子串是否是s1的一个排列,如果是,返回true。否则,继续比较。
利用s2中子串的长度必须与s1的长度相等这一特点,每次加入新的字符,就删去前面一个字符,这样长度一直相等,且是子串。 - 注意!数组的内容是否相等要用Arrays.equal函数,arr1.equals(arr2)不可以。
class Solution {
public boolean checkInclusion(String s1, String s2) {
int len1=s1.length();
int len2=s2.length();
if(len1>len2 || len1==0) {
return false;
}
int[] arr1=new int[128];
int[] arr2=new int[128];
for(int i=0;i<len1;i++) {
int value1=Integer.valueOf(s1.charAt(i));
arr1[value1]++;
int value2=Integer.valueOf(s2.charAt(i));
arr2[value2]++;
}
if(Arrays.equals(arr1,arr2 )) {
return true;
}
for(int i=len1;i<len2;i++) {
int value2=Integer.valueOf(s2.charAt(i));
arr2[value2]++;//装新的字符
int value22=Integer.valueOf(s2.charAt(i-len1));
arr2[value22]--;//删除早装入的字符,加一个删一个可以始终保持 当前正在比较的子串所形成的arr2的长度与s1的长度相同!!
if(Arrays.equals(arr1,arr2 )) {
return true;
}
}
return false;
}
}
网友评论