🎨Now live: Try our Free AI Image Generation Feature

Description
Given two strings s1 and s2, your goal is to determine if one string's permutation is a substring of the other. Specifically, check whether any permutation of s1 exists within s2. If so, return true, otherwise return false.
Intuition
The problem requires checking for a permutation of one string (s1) within the other (s2). A permutation involves rearranging characters, but since it’s only rearranging, the count of each character must match between the two strings. Thus, the task boils down to comparing character frequencies in sliding windows of s2 that match the length of s1.
Approach
- Initial Setup:
- Create two frequency arrays (or maps) to store character counts for
s1and the first window ins2of length equal tos1. - Sliding Window Technique:
- Use a sliding window over
s2, moving from the start to the end, adjusting the character frequencies dynamically for each window. - Compare the character counts of the current window ins2with the character counts ofs1. If they match, returntrue. - Edge Case:
- If
s1is longer thans2, directly returnfalsebecause it is impossible for a longer string to be a permutation of a shorter one.
Complexity
- Time Complexity: O(n), where
nis the length ofs2. Both strings1ands2are iterated once. Checking for matching frequencies is constant time since there are only 26 possible characters (for lowercase English letters). - Space Complexity: O(1), because the frequency array or map has a fixed size of 26 for lowercase characters, regardless of input size.
Code
C++
class Solution {
public:
bool checkInclusion(string s1, string s2) {
if (s1.size() > s2.size()) return false;
vector cache1(26, 0), cache2(26, 0);
for (int i = 0; i < s1.size(); ++i) {
cache1[s1[i] - 'a']++;
cache2[s2[i] - 'a']++;
}
auto checkCache = [&]() {
return cache1 == cache2;
};
if (checkCache()) return true;
for (int i = s1.size(); i < s2.size(); ++i) {
cache2[s2[i - s1.size()] - 'a']--;
cache2[s2[i] - 'a']++;
if (checkCache()) return true;
}
return false;
}
};
Python
class Solution:
def checkInclusion(self, s1: str, s2: str) -> bool:
if len(s1) > len(s2):
return False
cache1 = [0] * 26
cache2 = [0] * 26
for i in range(len(s1)):
cache1[ord(s1[i]) - ord('a')] += 1
cache2[ord(s2[i]) - ord('a')] += 1
if cache1 == cache2:
return True
for i in range(len(s1), len(s2)):
cache2[ord(s2[i - len(s1)]) - ord('a')] -= 1
cache2[ord(s2[i]) - ord('a')] += 1
if cache1 == cache2:
return True
return False
Java
class Solution {
public boolean checkInclusion(String s1, String s2) {
if (s1.length() > s2.length()) return false;
int[] cache1 = new int[26], cache2 = new int[26];
for (int i = 0; i < s1.length(); ++i) {
cache1[s1.charAt(i) - 'a']++;
cache2[s2.charAt(i) - 'a']++;
}
if (Arrays.equals(cache1, cache2)) return true;
for (int i = s1.length(); i < s2.length(); ++i) {
cache2[s2.charAt(i - s1.length()) - 'a']--;
cache2[s2.charAt(i) - 'a']++;
if (Arrays.equals(cache1, cache2)) return true;
}
return false;
}
}JavaScript
var checkInclusion = function (s1, s2) {
if (s1.length > s2.length) return false;
const cache1 = {};
const cache2 = {};
for (let i = 0; i < s1.length; i++) {
s1[i] in cache1 ? cache1[s1[i]]++ : cache1[s1[i]] = 1;
s2[i] in cache2 ? cache2[s2[i]]++ : cache2[s2[i]] = 1;
}
const checkCache = (cache1, cache2) => {
if (Object.values(cache1).length !== Object.values(cache2).length) return false;
for (const key in cache1) {
if (cache1[key] !== cache2[key]) {
return false;
}
}
return true;
}
if (checkCache(cache1, cache2)) return true;
for (let i = s1.length; i < s2.length; i++) {
let charOut = s2[i - s1.length];
cache2[charOut] === 1 ? delete cache2[charOut] : cache2[charOut]--;
let charIn = s2[i];
cache2[charIn] ? cache2[charIn]++ : cache2[charIn] = 1;
if (checkCache(cache1, cache2)) return true;
}
return false;
};