First, compute the frequency of each character in s1 and store it in an array or counter. This array will have a fixed size of 26 to represent each lowercase English letter.
Initial Window Setup:
Next, consider the first window of length equal to s1 in s2 and compute the frequency of characters in this window. This window represents the first possible substring of s2 that we will test to see if it matches s1.
Window Sliding Technique:
Compare the frequency array of the first window in s2 with the frequency array of s1. If they are equal, it means a permutation of s1 is found in s2, so return true.
If not, slide the window one character to the right. For each slide:
Increment the count of the new character added to the window.
Decrement the count of the character that is no longer in the window.
Compare the updated frequency array for the new window with s1’s frequency array.
If at any point the frequency arrays match, return true.
Completion:
If no matching window is found by the time we slide through the entire s2, return false as no permutation of s1 is a substring of s2.
⏰ Time complexity: O(n), where n is the length of s2. This is because we iterate through the s2 string a single time while maintaining a frequency count which is an O(1) operation due to the constant size of the alphabet (26 letters).
🧺 Space complexity: O(1), because we’re using fixed-size arrays, to store the frequency of characters, which do not scale with input size.
Permutation Check: To verify if string p is a permutation of string s, ensure every character in p exists in s. We can represent all permutations of s using a frequency map (Character -> Count). For example, abba becomes {a:2, b:2}. Given that there are only 26 lowercase letters, an array can efficiently represent this map.
Containment Check: To determine if s2 contains a permutation of s1, use a sliding window of length s1 across s2. As characters enter the window from the right, decrease their count in the map; as they exit from the left, increase their count. When all counts in the map reach zero, it indicates a matching frequency of characters between s
classSolution:
defcheckInclusion(self, s1: str, s2: str) -> bool:
len1, len2 = len(s1), len(s2)
if len1 > len2:
returnFalse count = [0] *26# Array to store character counts# Initialize the count array with the first windowfor i in range(len1):
count[ord(s1[i]) - ord('a')] +=1 count[ord(s2[i]) - ord('a')] -=1if self.allZero(count):
returnTrue# Slide the window over s2for i in range(len1, len2):
count[ord(s2[i]) - ord('a')] -=1 count[ord(s2[i - len1]) - ord('a')] +=1if self.allZero(count):
returnTruereturnFalsedefallZero(self, count):
for x in count:
if x !=0:
returnFalsereturnTrue
publicclassSolution {
publicbooleancheckInclusion(String s1, String s2) {
int[] count =newint[26]; // Array to hold the count of characters in s1for (char c : s1.toCharArray()) {
count[c -'a']++;
}
int l = 0, r = 0;
int m = s1.length(), n = s2.length();
int diffs = m; // Number of differing characters// Iterate over s2 with two pointerswhile (r < s2.length()) {
// Decrement the count of the character entering the windowif (count[s2.charAt(r++) -'a']--> 0) {
diffs--;
}
// If diffs is zero, we found a valid permutation matchif (diffs == 0) {
returntrue;
}
// When the window size exceeds s1.length(), update the left pointerif (r - l == m && count[s2.charAt(l++) -'a']++>= 0) {
diffs++;
}
}
returnfalse;
}
}
classSolution:
defcheckInclusion(self, s1: str, s2: str) -> bool:
count = [0] *26# Array to hold the count of characters in s1for c in s1:
count[ord(c) - ord('a')] +=1 l, r =0, 0 diffs = len(s1) # Number of differing characters# Iterate over s2 with two pointerswhile r < len(s2):
# Decrement the count of the character entering the windowif count[ord(s2[r]) - ord('a')] >0:
diffs -=1 count[ord(s2[r]) - ord('a')] -=1 r +=1# If diffs is zero, we found a valid permutation matchif diffs ==0:
returnTrue# When the window size exceeds s1.length(), update the left pointerif r - l == len(s1):
if count[ord(s2[l]) - ord('a')] >=0:
diffs +=1 count[ord(s2[l]) - ord('a')] +=1 l +=1returnFalse