Permutation in String - shilpathota/99-leetcode-solutions GitHub Wiki
Leet code link - https://leetcode.com/problems/permutation-in-string/description/
Given two strings s1 and s2, return true if s2 contains a permutation of s1, or false otherwise.
In other words, return true if one of s1's permutations is the substring of s2.
Input: s1 = "ab", s2 = "eidbaooo"
Output: true
Explanation: s2 contains one permutation of s1 ("ba").
Input: s1 = "ab", s2 = "eidboaoo"
Output: false
1 <= s1.length, s2.length <= 104
s1 and s2 consist of lowercase English letters.
The idea behind this approach is that one string will be a permutation of another string only if both of them contain the same characters the same number of times. One string x is a permutation of other string y only if sorted(x)=sorted(y).
In order to check this, we can sort the two strings and compare them. We sort the short string s1 and all the substrings of s2, sort them and compare them with the sorted s1 string. If the two matches completely, s1's permutation is a substring of s2, otherwise not.
public class Solution {
public boolean checkInclusion(String s1, String s2) {
s1 = sort(s1);
for (int i = 0; i <= s2.length() - s1.length(); i++) {
if (s1.equals(sort(s2.substring(i, i + s1.length()))))
return true;
}
return false;
}
public String sort(String s) {
char[] t = s.toCharArray();
Arrays.sort(t);
return new String(t);
}
}
Let l 1 be the length of string s 1 and l 2 be the length of string s 2 .
Time complexity: O((l 2 −l 1 )⋅l 1 logl 1 ).
Space Complexity - O(l1+S).t
We can use HashMap to reduce the complexity where we store the count of characters of first string and then while moving over the second string I can store the count but can remove the characters as we move through the window.
class Solution {
public boolean checkInclusion(String s1, String s2) {
//count of s1 string
if (s1.length() > s2.length())
return false;
HashMap<Character, Integer> s1map = new HashMap<>();
for (int i = 0; i < s1.length(); i++)
s1map.put(s1.charAt(i), s1map.getOrDefault(s1.charAt(i), 0) + 1);
//count of s2 string but substring whose length is equal to s1
for (int i = 0; i <= s2.length() - s1.length(); i++) {
HashMap<Character, Integer> s2map = new HashMap<>();
for (int j = 0; j < s1.length(); j++) {
s2map.put(s2.charAt(i + j), s2map.getOrDefault(s2.charAt(i + j), 0) + 1);
}
if (matches(s1map, s2map))
return true;
}
return false;
}
public boolean matches(HashMap<Character, Integer> s1map, HashMap<Character, Integer> s2map) {
for (char key : s1map.keySet()) {
if (s1map.get(key) - s2map.getOrDefault(key, -1) != 0)
return false;
}
return true;
}
}
We can also use array and the optimal solution is given below
public class Solution {
public boolean checkInclusion(String s1, String s2) {
if (s1.length() > s2.length())
return false;
int[] s1arr = new int[26];
int[] s2arr = new int[26];
for (int i = 0; i < s1.length(); i++) {
s1arr[s1.charAt(i) - 'a']++;
s2arr[s2.charAt(i) - 'a']++;
}
for (int i = 0; i < s2.length() - s1.length(); i++) {
if (matches(s1arr, s2arr))
return true;
s2arr[s2.charAt(i + s1.length()) - 'a']++;
s2arr[s2.charAt(i) - 'a']--;
}
return matches(s1arr, s2arr);
}
public boolean matches(int[] s1arr, int[] s2arr) {
for (int i = 0; i < 26; i++) {
if (s1arr[i] != s2arr[i])
return false;
}
return true;
}
}
Time Complexity is O(l2) and Space complexity is O(1)