Skip to content

Commit 5cd1ea3

Browse files
committed
Problem: Permutation in a String
1 parent 15bf2cf commit 5cd1ea3

File tree

3 files changed

+104
-0
lines changed

3 files changed

+104
-0
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
2+
# Problem: Permutation in a String
3+
4+
LeetCode problem: [567. Permutation in String](https://leetcode.com/problems/permutation-in-string/).
5+
6+
Given a pattern and a string, find out if the string contains any permutation of the pattern.
7+
8+
Permutation is defined as the re-arranging of the characters of the string. For example, `abc` has the following six permutations: `abc`, `acb`, `bac`, `bca`, `cab`, `cba`.
9+
10+
## Examples
11+
12+
Example 1:
13+
14+
```plaintext
15+
Input: Pattern = "abc", String = "oidbcaf"
16+
Output: true
17+
Explanation: The string contains "bca" which is a permutation of the given pattern.
18+
```
19+
20+
Example 2:
21+
22+
```plaintext
23+
Input: Pattern = "dc", String = "odicf"
24+
Output: false
25+
Explanation: No permutation of the pattern is present in the given string as a substring.
26+
```
27+
28+
Example 3:
29+
30+
```plaintext
31+
Input: Pattern = "bcdyabcdx", String = "bcdxabcdy"
32+
Output: true
33+
Explanation: Both the string and the pattern are a permutation of each other.
34+
```
35+
36+
Example 4:
37+
38+
```plaintext
39+
Input: Pattern = "abc", String = "aaacb"
40+
Output: true
41+
Explanation: The string contains "acb" which is a permutation of the given pattern.
42+
```
43+
44+
## Solution
45+
46+
The algorithm uses a sliding window of the same length as the input pattern. It maintains a frequency counter of the pattern's characters and compares this to the frequency of characters in the sliding window of the target string as the window moves over the string.
47+
48+
Here are the steps of the algorithm:
49+
50+
1. Create a counter to track the frequencies of all characters in the pattern string.
51+
2. Iterate through the target string, adding one character at a time in the sliding window while maintaining a window of the same length as the pattern.
52+
3. For each new character added to the window, decrease its frequency in the counter if it matches a character in the pattern. If its frequency reaches zero, that character is fully matched.
53+
4. If at any time, the number of matched characters equals the number of unique characters in the pattern string, the window contains a permutation of the pattern.
54+
5. When the window exceeds the pattern's length, the window is shrunk by removing the leftmost character, restoring its frequency in the counter if it belongs to the pattern and adjust the matched count accordingly.
55+
56+
Complexity analysis:
57+
58+
- Time complexity: O(N + M)
59+
- Space complexity: O(N) or O(1) if `s1` and `s2` consist of lowercase English letters only.
60+
61+
Where:
62+
63+
- `N` is the length of `s1` (the pattern string).
64+
- `M` is the length of `s2` (the target string).
65+
66+
```python
67+
def checkInclusion(s1: str, s2: str) -> bool:
68+
# O(N) time and O(N) space
69+
s1_counter = Counter(s1)
70+
71+
window_start = 0
72+
window_matched_characters = 0
73+
for window_end in range(len(s2)):
74+
window_end_character = s2[window_end]
75+
76+
# if the character is part of s1, decrease its frequency in the counter
77+
if window_end_character in s1_counter:
78+
s1_counter[window_end_character] -= 1
79+
80+
# if the frequency becomes zero, it means we have matched all instances of this character
81+
if s1_counter[window_end_character] == 0:
82+
window_matched_characters += 1
83+
84+
# if all characters from s1 are matched, return True
85+
if window_matched_characters == len(s1_counter):
86+
return True
87+
88+
# shrink the window when its length is longer than the pattern length
89+
if window_end >= len(s1) - 1:
90+
window_start_character = s2[window_start]
91+
92+
# if the character that is leaving is part of s1, increment its frequency back in the counter
93+
if window_start_character in s1_counter:
94+
# if the character was previously fully matched, we lose the match for it
95+
if s1_counter[window_start_character] == 0:
96+
window_matched_characters -= 1
97+
s1_counter[window_start_character] += 1
98+
99+
window_start += 1
100+
101+
return False
102+
```

03-sliding-window/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ This technique is often used for solving problems that require processing or ana
1515
| [No-repeat Substring](./05-no-repeat-substring.md) | :star2: :star2: :star2: |
1616
| [Longest Substring with Same Letters after Replacement](./06-longest-substring-with-same-letters-after-replacement.md) | :star2: :star2: :star2: |
1717
| [Longest Subarray with Ones after Replacement](./07-longest-subarray-with-ones-after-replacement.md) | :star2: :star2: :star2: |
18+
| [Permutation in a String](./08-permutation-in-a-string.md) | :star2: :star2: :star2: |

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ This repository contains my solutions and notes for the Educative's [Grokking Co
4242
| [No-repeat Substring](./03-sliding-window/05-no-repeat-substring.md) |
4343
| [Longest Substring with Same Letters after Replacement](./03-sliding-window/06-longest-substring-with-same-letters-after-replacement.md) |
4444
| [Longest Subarray with Ones after Replacement](./03-sliding-window/07-longest-subarray-with-ones-after-replacement.md) |
45+
| [Permutation in a String](./03-sliding-window/08-permutation-in-a-string.md) |
4546

4647
## Courses
4748

0 commit comments

Comments
 (0)