Skip to content

Commit e51eea7

Browse files
Add 'Permutation in String'
1 parent 7d0e59e commit e51eea7

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ A collection of LeetCode solutions
6464

6565
[Minimum Size Subarray Sum](./src/minimum_size_subarray_sum.py)
6666

67+
[Permutation in String](./src/permutation_in_string.py)
68+
6769
[Product of Array Except Self](./src/product_of_array_except_self.py)
6870

6971
[Remove Nth Node From End of List](./src/remove_nth_node_from_end_of_list.py)

src/permutation_in_string.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"""
2+
567. Permutation in String
3+
4+
https://leetcode.com/problems/permutation-in-string
5+
6+
NOTES
7+
* Use a sliding window.
8+
9+
I tried to get fancy with this one and use bitwise operations. This failed.
10+
Just use a hash map or, better still, an array of size 26 (one index for each
11+
character).
12+
"""
13+
14+
from collections import Counter
15+
16+
17+
class Solution:
18+
def checkInclusion(self, s1: str, s2: str) -> bool:
19+
left, right = 0, len(s1)
20+
21+
# Create a mapping of character -> frequency. Here, it is advantageous
22+
# to use an instance of Counter, however an ordinary dict would work
23+
# just as well.
24+
s1_counter: Counter[str] = Counter(s1)
25+
s2_counter: Counter[str] = Counter(s2[: len(s1)])
26+
27+
while right < len(s2):
28+
if s1_counter == s2_counter:
29+
return True
30+
s2_counter[s2[right]] += 1
31+
right += 1
32+
s2_counter[s2[left]] -= 1
33+
left += 1
34+
35+
# Add final equality check.
36+
return s1_counter == s2_counter
37+
38+
39+
class ArraySolution:
40+
def checkInclusion(self, s1: str, s2: str) -> bool:
41+
def offset(c: str) -> int:
42+
return ord(c) - ord("a")
43+
44+
left, right = 0, len(s1)
45+
46+
# Use an array of size 26. NOTE: In order to offset a character so that
47+
# it is between 0 and 25, use:
48+
#
49+
# ord(c) - ord('a')
50+
s1_counter: list[int] = [0] * 26
51+
s2_counter: list[int] = [0] * 26
52+
53+
for i in range(len(s1)):
54+
s1_counter[offset(s1[i])] += 1
55+
56+
for i in range(len(s1)):
57+
s2_counter[offset(s2[i])] += 1
58+
59+
while right < len(s2):
60+
if s1_counter == s2_counter:
61+
return True
62+
s2_counter[offset(s2[right])] += 1
63+
right += 1
64+
s2_counter[offset(s2[left])] -= 1
65+
left += 1
66+
67+
# Add final equality check.
68+
return s1_counter == s2_counter

tests/test_permutation_in_string.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""
2+
567. Permutation in String
3+
4+
https://leetcode.com/problems/permutation-in-string
5+
"""
6+
7+
from unittest import TestCase
8+
9+
from src.permutation_in_string import ArraySolution, Solution
10+
11+
12+
class TestSolution(TestCase):
13+
def test_1(self):
14+
exp = True
15+
assert Solution().checkInclusion("ab", "eidbaooo") == exp
16+
17+
def test_2(self):
18+
exp = False
19+
assert Solution().checkInclusion("ab", "eidboaoo") == exp
20+
21+
def test_3(self):
22+
exp = False
23+
assert Solution().checkInclusion("hello", "ooolleoooleh") == exp
24+
25+
def test_4(self):
26+
exp = False
27+
assert Solution().checkInclusion("dd", "rroogzkdktk") == exp
28+
29+
30+
class TestArraySolution(TestCase):
31+
def test_1(self):
32+
exp = True
33+
assert ArraySolution().checkInclusion("ab", "eidbaooo") == exp
34+
35+
def test_2(self):
36+
exp = False
37+
assert ArraySolution().checkInclusion("ab", "eidboaoo") == exp
38+
39+
def test_3(self):
40+
exp = False
41+
assert ArraySolution().checkInclusion("hello", "ooolleoooleh") == exp
42+
43+
def test_4(self):
44+
exp = False
45+
assert ArraySolution().checkInclusion("dd", "rroogzkdktk") == exp

0 commit comments

Comments
 (0)