Skip to content

Commit 7712d22

Browse files
authored
feat: add palindrome partitioning (#100)
1 parent 0c4d8c6 commit 7712d22

File tree

8 files changed

+216
-1
lines changed

8 files changed

+216
-1
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ repos:
1616
- id: check-added-large-files
1717
args: ["--maxkb=20000"]
1818
- repo: https://github.com/gitleaks/gitleaks
19-
rev: v8.29.1
19+
rev: v8.30.0
2020
hooks:
2121
- name: gitleaks
2222
id: gitleaks
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Palindrome Partitioning
2+
3+
**Difficulty:** Medium
4+
**Topics:** String, Dynamic Programming, Backtracking
5+
**Tags:** grind-75
6+
7+
**LeetCode:** [Problem 131](https://leetcode.com/problems/palindrome-partitioning/description/)
8+
9+
## Problem Description
10+
11+
Given a string `s`, partition `s` such that every substring of the partition is a **palindrome**. Return _all possible palindrome partitioning of `s`_.
12+
13+
## Examples
14+
15+
### Example 1:
16+
17+
```
18+
Input: s = "aab"
19+
Output: [["a","a","b"],["aa","b"]]
20+
```
21+
22+
### Example 2:
23+
24+
```
25+
Input: s = "a"
26+
Output: [["a"]]
27+
```
28+
29+
## Constraints
30+
31+
- `1 <= s.length <= 16`
32+
- `s` contains only lowercase English letters.

leetcode/palindrome_partitioning/__init__.py

Whitespace-only changes.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
def run_partition(solution_class: type, s: str):
2+
implementation = solution_class()
3+
return implementation.partition(s)
4+
5+
6+
def assert_partition(result: list[list[str]], expected: list[list[str]]) -> bool:
7+
# Sort inner lists and outer list for comparison
8+
# Note: Inner lists are partitions (lists of strings), order of partitions doesn't matter
9+
# Order of strings within a partition DOES matter (it must reconstruct s)
10+
# But wait, the problem says "partition s", so the order of substrings must match the order in s.
11+
# So we only need to sort the outer list of partitions.
12+
result_sorted = sorted(result)
13+
expected_sorted = sorted(expected)
14+
assert result_sorted == expected_sorted
15+
return True
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# ---
2+
# jupyter:
3+
# jupytext:
4+
# text_representation:
5+
# extension: .py
6+
# format_name: percent
7+
# format_version: '1.3'
8+
# jupytext_version: 1.18.1
9+
# kernelspec:
10+
# display_name: leetcode-py-py3.13
11+
# language: python
12+
# name: python3
13+
# ---
14+
15+
# %%
16+
from helpers import assert_partition, run_partition
17+
from solution import Solution
18+
19+
# %%
20+
# Example test case
21+
s = "aab"
22+
expected = [["a", "a", "b"], ["aa", "b"]]
23+
24+
# %%
25+
result = run_partition(Solution, s)
26+
result
27+
28+
# %%
29+
assert_partition(result, expected)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class Solution:
2+
# Time: O(N * 2^N)
3+
# Space: O(N)
4+
def partition(self, s: str) -> list[list[str]]:
5+
result: list[list[str]] = []
6+
self._backtrack(s, 0, [], result)
7+
return result
8+
9+
def _backtrack(self, s: str, start: int, path: list[str], result: list[list[str]]) -> None:
10+
if start == len(s):
11+
result.append(path[:])
12+
return
13+
14+
for end in range(start + 1, len(s) + 1):
15+
substring = s[start:end]
16+
if self._is_palindrome(substring):
17+
path.append(substring)
18+
self._backtrack(s, end, path, result)
19+
path.pop()
20+
21+
def _is_palindrome(self, s: str) -> bool:
22+
return s == s[::-1]
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import pytest
2+
3+
from leetcode_py import logged_test
4+
5+
from .helpers import assert_partition, run_partition
6+
from .solution import Solution
7+
8+
9+
class TestPalindromePartitioning:
10+
def setup_method(self):
11+
self.solution = Solution()
12+
13+
@logged_test
14+
@pytest.mark.parametrize(
15+
"s, expected",
16+
[
17+
("aab", [["a", "a", "b"], ["aa", "b"]]),
18+
("a", [["a"]]),
19+
("ab", [["a", "b"]]),
20+
("aa", [["a", "a"], ["aa"]]),
21+
("abc", [["a", "b", "c"]]),
22+
("aba", [["a", "b", "a"], ["aba"]]),
23+
("aaa", [["a", "a", "a"], ["a", "aa"], ["aa", "a"], ["aaa"]]),
24+
("abba", [["a", "b", "b", "a"], ["a", "bb", "a"], ["abba"]]),
25+
("zz", [["z", "z"], ["zz"]]),
26+
("efe", [["e", "f", "e"], ["efe"]]),
27+
("xyx", [["x", "y", "x"], ["xyx"]]),
28+
("noon", [["n", "o", "o", "n"], ["n", "oo", "n"], ["noon"]]),
29+
],
30+
)
31+
def test_partition(self, s: str, expected: list[list[str]]):
32+
result = run_partition(Solution, s)
33+
assert_partition(result, expected)
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
{
2+
"problem_name": "palindrome_partitioning",
3+
"solution_class_name": "Solution",
4+
"problem_number": "131",
5+
"problem_title": "Palindrome Partitioning",
6+
"difficulty": "Medium",
7+
"topics": "String, Dynamic Programming, Backtracking",
8+
"readme_description": "Given a string `s`, partition `s` such that every substring of the partition is a **palindrome**. Return *all possible palindrome partitioning of `s`*.",
9+
"_readme_examples": {
10+
"list": [
11+
{
12+
"content": "```\nInput: s = \"aab\"\nOutput: [[\"a\",\"a\",\"b\"],[\"aa\",\"b\"]]\n```"
13+
},
14+
{
15+
"content": "```\nInput: s = \"a\"\nOutput: [[\"a\"]]\n```"
16+
}
17+
]
18+
},
19+
"readme_constraints": "- `1 <= s.length <= 16`\n- `s` contains only lowercase English letters.",
20+
"readme_additional": "",
21+
"helpers_imports": "",
22+
"helpers_content": "",
23+
"helpers_run_name": "partition",
24+
"helpers_run_signature": "(solution_class: type, s: str)",
25+
"helpers_run_body": " implementation = solution_class()\n return implementation.partition(s)",
26+
"helpers_assert_name": "partition",
27+
"helpers_assert_signature": "(result: list[list[str]], expected: list[list[str]]) -> bool",
28+
"helpers_assert_body": " # Sort inner lists and outer list for comparison\n # Note: Inner lists are partitions (lists of strings), order of partitions doesn't matter\n # Order of strings within a partition DOES matter (it must reconstruct s)\n # But wait, the problem says \"partition s\", so the order of substrings must match the order in s.\n # So we only need to sort the outer list of partitions.\n result_sorted = sorted(result)\n expected_sorted = sorted(expected)\n assert result_sorted == expected_sorted\n return True",
29+
"solution_imports": "",
30+
"solution_contents": "",
31+
"solution_class_content": "",
32+
"test_imports": "import pytest\nfrom leetcode_py import logged_test\nfrom .helpers import assert_partition, run_partition\nfrom .solution import Solution",
33+
"test_content": "",
34+
"test_class_name": "PalindromePartitioning",
35+
"test_class_content": " def setup_method(self):\n self.solution = Solution()",
36+
"_solution_methods": {
37+
"list": [
38+
{
39+
"name": "partition",
40+
"signature": "(self, s: str) -> list[list[str]]",
41+
"body": " # TODO: Implement partition\n return []"
42+
}
43+
]
44+
},
45+
"_test_helper_methods": {
46+
"list": [
47+
{
48+
"name": "setup_method",
49+
"parameters": "",
50+
"body": "self.solution = Solution()"
51+
}
52+
]
53+
},
54+
"_test_methods": {
55+
"list": [
56+
{
57+
"name": "test_partition",
58+
"signature": "(self, s: str, expected: list[list[str]])",
59+
"parametrize": "s, expected",
60+
"test_cases": {
61+
"list": [
62+
"('aab', [['a', 'a', 'b'], ['aa', 'b']])",
63+
"('a', [['a']])",
64+
"('ab', [['a', 'b']])",
65+
"('aa', [['a', 'a'], ['aa']])",
66+
"('abc', [['a', 'b', 'c']])",
67+
"('aba', [['a', 'b', 'a'], ['aba']])",
68+
"('aaa', [['a', 'a', 'a'], ['a', 'aa'], ['aa', 'a'], ['aaa']])",
69+
"('abba', [['a', 'b', 'b', 'a'], ['a', 'bb', 'a'], ['abba']])",
70+
"('zz', [['z', 'z'], ['zz']])",
71+
"('efe', [['e', 'f', 'e'], ['efe']])",
72+
"('xyx', [['x', 'y', 'x'], ['xyx']])",
73+
"('noon', [['n', 'o', 'o', 'n'], ['n', 'oo', 'n'], ['noon']])"
74+
]
75+
},
76+
"body": " result = run_partition(Solution, s)\n assert_partition(result, expected)"
77+
}
78+
]
79+
},
80+
"playground_imports": "from helpers import run_partition, assert_partition\nfrom solution import Solution",
81+
"playground_setup": "# Example test case\ns = 'aab'\nexpected = [['a', 'a', 'b'], ['aa', 'b']]",
82+
"playground_run": "result = run_partition(Solution, s)\nresult",
83+
"playground_assert": "assert_partition(result, expected)"
84+
}

0 commit comments

Comments
 (0)