Permutation in String
Given two strings s1s2trues2s1
Example 1
Output: true
Explanation: s2 contains "ba".
Example 2
Output: false
How to Think About It
Step 1: What a permutation means here
A substring is a permutation of s1
Step 2: Slide a window of length n = s1.length()
Only substrings of length ns2
Step 3: Track the difference, not two count arrays
Keep diff[c]cs1c
Comparing all 26 entries at every step would work, but we can do better: keep zeroszeroszeros == 26
Walkthrough
s1 = "ab"s2 = "eidbaooo"diff
| Window | diff[a] | diff[b] | Other letters all 0? | Match? |
|---|---|---|---|---|
| ei | 1 | 1 | no (e, i are -1) | no |
| id | 1 | 1 | no | no |
| db | 1 | 0 | no (d is -1) | no |
| ba | 0 | 0 | yes | yes: return true |
Java Solution
The helper change
public class PermutationInString {
public static boolean checkInclusion(String s1, String s2) {
int n = s1.length();
if (n > s2.length()) {
return false;
}
int[] diff = new int[26]; // count in s1 minus count in the window
for (int i = 0; i < n; i++) {
diff[s1.charAt(i) - 'a']++;
diff[s2.charAt(i) - 'a']--;
}
int zeros = 0; // letters whose counts match
for (int d : diff) {
if (d == 0) {
zeros++;
}
}
for (int i = n; ; i++) {
if (zeros == 26) {
return true; // the window is a permutation of s1
}
if (i == s2.length()) {
return false;
}
zeros += change(diff, s2.charAt(i) - 'a', -1); // letter enters the window
zeros += change(diff, s2.charAt(i - n) - 'a', +1); // letter leaves the window
}
}
// Apply delta to diff[c]; return how the number of zero entries changed (-1, 0 or +1)
private static int change(int[] diff, int c, int delta) {
int before = diff[c] == 0 ? 1 : 0;
diff[c] += delta;
int after = diff[c] == 0 ? 1 : 0;
return after - before;
}
public static void main(String[] args) {
System.out.println(checkInclusion("ab", "eidbaooo")); // true
System.out.println(checkInclusion("ab", "eidboaoo")); // false
}
}
The original implementation,
Complexity
- Time: O(n + m): constant work per step.
- Space: O(1): 26 counters.
To list every match instead of stopping at the first, see