Skip to content

Commit 61ef1f6

Browse files
committed
feat: add Permutations
1 parent b422baf commit 61ef1f6

File tree

13 files changed

+419
-1
lines changed

13 files changed

+419
-1
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"problem_name": "combination_sum",
3+
"solution_class_name": "Solution",
4+
"problem_number": "39",
5+
"problem_title": "Combination Sum",
6+
"difficulty": "Medium",
7+
"topics": "Array, Backtracking",
8+
"tags": ["grind-75"],
9+
"readme_description": "Given an array of **distinct** integers `candidates` and a target integer `target`, return *a list of all **unique combinations** of* `candidates` *where the chosen numbers sum to* `target`. You may return the combinations in **any order**.\n\nThe **same** number may be chosen from `candidates` an **unlimited number of times**. Two combinations are unique if the frequency of at least one of the chosen numbers is different.\n\nThe test cases are generated such that the number of unique combinations that sum up to `target` is less than `150` combinations for the given input.",
10+
"readme_examples": [
11+
{
12+
"content": "```\nInput: candidates = [2,3,6,7], target = 7\nOutput: [[2,2,3],[7]]\n```\n**Explanation:** 2 and 3 are candidates, and 2 + 2 + 3 = 7. Note that 2 can be used multiple times. 7 is a candidate, and 7 = 7. These are the only two combinations."
13+
},
14+
{
15+
"content": "```\nInput: candidates = [2,3,5], target = 8\nOutput: [[2,2,2,2],[2,3,3],[3,5]]\n```"
16+
},
17+
{ "content": "```\nInput: candidates = [2], target = 1\nOutput: []\n```" }
18+
],
19+
"readme_constraints": "- 1 <= candidates.length <= 30\n- 2 <= candidates[i] <= 40\n- All elements of candidates are distinct.\n- 1 <= target <= 40",
20+
"readme_additional": "",
21+
"solution_imports": "",
22+
"solution_methods": [
23+
{
24+
"name": "combination_sum",
25+
"parameters": "candidates: list[int], target: int",
26+
"return_type": "list[list[int]]",
27+
"dummy_return": "[]"
28+
}
29+
],
30+
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .solution import Solution",
31+
"test_class_name": "CombinationSum",
32+
"test_helper_methods": [
33+
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
34+
],
35+
"test_methods": [
36+
{
37+
"name": "test_combination_sum",
38+
"parametrize": "candidates, target, expected",
39+
"parametrize_typed": "candidates: list[int], target: int, expected: list[list[int]]",
40+
"test_cases": "[([2, 3, 6, 7], 7, [[2, 2, 3], [7]]), ([2, 3, 5], 8, [[2, 2, 2, 2], [2, 3, 3], [3, 5]]), ([2], 1, [])]",
41+
"body": "result = self.solution.combination_sum(candidates, target)\n# Sort both result and expected for comparison\nresult_sorted = [sorted(combo) for combo in result]\nexpected_sorted = [sorted(combo) for combo in expected]\nresult_sorted.sort()\nexpected_sorted.sort()\nassert result_sorted == expected_sorted"
42+
}
43+
],
44+
"playground_imports": "from solution import Solution",
45+
"playground_test_case": "# Example test case\ncandidates = [2, 3, 6, 7]\ntarget = 7\nexpected = [[2, 2, 3], [7]]",
46+
"playground_execution": "result = Solution().combination_sum(candidates, target)\nresult",
47+
"playground_assertion": "# Sort for comparison\nresult_sorted = [sorted(combo) for combo in result]\nexpected_sorted = [sorted(combo) for combo in expected]\nresult_sorted.sort()\nexpected_sorted.sort()\nassert result_sorted == expected_sorted"
48+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"problem_name": "permutations",
3+
"solution_class_name": "Solution",
4+
"problem_number": "46",
5+
"problem_title": "Permutations",
6+
"difficulty": "Medium",
7+
"topics": "Array, Backtracking",
8+
"tags": ["grind-75"],
9+
"readme_description": "Given an array `nums` of distinct integers, return all the possible permutations. You can return the answer in any order.",
10+
"readme_examples": [
11+
{
12+
"content": "```\nInput: nums = [1,2,3]\nOutput: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]\n```"
13+
},
14+
{ "content": "```\nInput: nums = [0,1]\nOutput: [[0,1],[1,0]]\n```" },
15+
{ "content": "```\nInput: nums = [1]\nOutput: [[1]]\n```" }
16+
],
17+
"readme_constraints": "- 1 <= nums.length <= 6\n- -10 <= nums[i] <= 10\n- All the integers of nums are unique.",
18+
"readme_additional": "",
19+
"solution_imports": "",
20+
"solution_methods": [
21+
{
22+
"name": "permute",
23+
"parameters": "nums: list[int]",
24+
"return_type": "list[list[int]]",
25+
"dummy_return": "[]"
26+
}
27+
],
28+
"test_imports": "import pytest\nfrom leetcode_py.test_utils import logged_test\nfrom .solution import Solution",
29+
"test_class_name": "TestPermutations",
30+
"test_helper_methods": [
31+
{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }
32+
],
33+
"test_methods": [
34+
{
35+
"name": "test_permute",
36+
"parametrize": "nums, expected",
37+
"parametrize_typed": "nums: list[int], expected: list[list[int]]",
38+
"test_cases": "[([1, 2, 3], [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]), ([0, 1], [[0, 1], [1, 0]]), ([1], [[1]])]",
39+
"body": "result = self.solution.permute(nums)\n # Sort both result and expected for comparison since order doesn't matter\n result_sorted = [sorted(perm) for perm in result]\n expected_sorted = [sorted(perm) for perm in expected]\n result_sorted.sort()\n expected_sorted.sort()\n assert len(result) == len(expected)\n assert result_sorted == expected_sorted"
40+
}
41+
],
42+
"playground_imports": "from solution import Solution",
43+
"playground_test_case": "# Example test case\nnums = [1, 2, 3]\nexpected = [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]",
44+
"playground_execution": "result = Solution().permute(nums)\nresult",
45+
"playground_assertion": "# Check that we have the right number of permutations\nassert len(result) == len(expected)\n# Sort for comparison since order doesn't matter\nresult_sorted = [sorted(perm) for perm in result]\nexpected_sorted = [sorted(perm) for perm in expected]\nresult_sorted.sort()\nexpected_sorted.sort()\nassert result_sorted == expected_sorted"
46+
}

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
PYTHON_VERSION = 3.13
2-
PROBLEM ?= rotting_oranges
2+
PROBLEM ?= permutations
33
FORCE ?= 0
44
COMMA := ,
55

leetcode/combination_sum/README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Combination Sum
2+
3+
**Difficulty:** Medium
4+
**Topics:** Array, Backtracking
5+
**Tags:** grind-75
6+
7+
**LeetCode:** [Problem 39](https://leetcode.com/problems/combination-sum/description/)
8+
9+
## Problem Description
10+
11+
Given an array of **distinct** integers `candidates` and a target integer `target`, return _a list of all **unique combinations** of_ `candidates` _where the chosen numbers sum to_ `target`. You may return the combinations in **any order**.
12+
13+
The **same** number may be chosen from `candidates` an **unlimited number of times**. Two combinations are unique if the frequency of at least one of the chosen numbers is different.
14+
15+
The test cases are generated such that the number of unique combinations that sum up to `target` is less than `150` combinations for the given input.
16+
17+
## Examples
18+
19+
### Example 1:
20+
21+
```
22+
Input: candidates = [2,3,6,7], target = 7
23+
Output: [[2,2,3],[7]]
24+
```
25+
26+
**Explanation:** 2 and 3 are candidates, and 2 + 2 + 3 = 7. Note that 2 can be used multiple times. 7 is a candidate, and 7 = 7. These are the only two combinations.
27+
28+
### Example 2:
29+
30+
```
31+
Input: candidates = [2,3,5], target = 8
32+
Output: [[2,2,2,2],[2,3,3],[3,5]]
33+
```
34+
35+
### Example 3:
36+
37+
```
38+
Input: candidates = [2], target = 1
39+
Output: []
40+
```
41+
42+
## Constraints
43+
44+
- 1 <= candidates.length <= 30
45+
- 2 <= candidates[i] <= 40
46+
- All elements of candidates are distinct.
47+
- 1 <= target <= 40

leetcode/combination_sum/__init__.py

Whitespace-only changes.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"id": "imports",
7+
"metadata": {},
8+
"outputs": [],
9+
"source": ["from solution import Solution"]
10+
},
11+
{
12+
"cell_type": "code",
13+
"execution_count": null,
14+
"id": "setup",
15+
"metadata": {},
16+
"outputs": [],
17+
"source": ["# Example test case\ncandidates = [2, 3, 6, 7]\ntarget = 7\nexpected = [[2, 2, 3], [7]]"]
18+
},
19+
{
20+
"cell_type": "code",
21+
"execution_count": null,
22+
"id": "execute",
23+
"metadata": {},
24+
"outputs": [],
25+
"source": ["result = Solution().combination_sum(candidates, target)\nresult"]
26+
},
27+
{
28+
"cell_type": "code",
29+
"execution_count": null,
30+
"id": "test",
31+
"metadata": {},
32+
"outputs": [],
33+
"source": ["# Sort for comparison\nresult_sorted = [sorted(combo) for combo in result]\nexpected_sorted = [sorted(combo) for combo in expected]\nresult_sorted.sort()\nexpected_sorted.sort()\nassert result_sorted == expected_sorted"]
34+
}
35+
],
36+
"metadata": {
37+
"kernelspec": {
38+
"display_name": "leetcode-py-py3.13",
39+
"language": "python",
40+
"name": "python3"
41+
},
42+
"language_info": {
43+
"codemirror_mode": {
44+
"name": "ipython",
45+
"version": 3
46+
},
47+
"file_extension": ".py",
48+
"mimetype": "text/x-python",
49+
"name": "python",
50+
"nbconvert_exporter": "python3",
51+
"pygments_lexer": "ipython3",
52+
"version": "3.13.7"
53+
}
54+
},
55+
"nbformat": 4,
56+
"nbformat_minor": 5
57+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
class Solution:
2+
# Time: O(N^(T/M)) where N=len(candidates), T=target, M=min(candidates)
3+
# Space: O(T/M) recursion + O(K * T/M) output, where K = number of solutions
4+
def combination_sum(self, candidates: list[int], target: int) -> list[list[int]]:
5+
result = []
6+
7+
def backtrack(start: int, path: list[int], remaining: int) -> None:
8+
if remaining == 0:
9+
result.append(path[:])
10+
return
11+
12+
for i in range(start, len(candidates)):
13+
if candidates[i] <= remaining:
14+
path.append(candidates[i])
15+
backtrack(i, path, remaining - candidates[i])
16+
path.pop()
17+
18+
backtrack(0, [], target)
19+
return result

leetcode/combination_sum/tests.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import pytest
2+
3+
from leetcode_py.test_utils import logged_test
4+
5+
from .solution import Solution
6+
7+
8+
class TestCombinationSum:
9+
def setup_method(self):
10+
self.solution = Solution()
11+
12+
@pytest.mark.parametrize(
13+
"candidates, target, expected",
14+
[
15+
([2, 3, 6, 7], 7, [[2, 2, 3], [7]]),
16+
([2, 3, 5], 8, [[2, 2, 2, 2], [2, 3, 3], [3, 5]]),
17+
([2], 1, []),
18+
([1], 1, [[1]]),
19+
([1], 2, [[1, 1]]),
20+
([2, 3, 4], 6, [[2, 2, 2], [2, 4], [3, 3]]),
21+
(
22+
[7, 3, 2],
23+
18,
24+
[
25+
[2, 2, 2, 2, 2, 2, 2, 2, 2],
26+
[2, 2, 2, 2, 2, 2, 3, 3],
27+
[2, 2, 2, 3, 3, 3, 3],
28+
[2, 2, 7, 7],
29+
[2, 3, 3, 3, 7],
30+
[3, 3, 3, 3, 3, 3],
31+
],
32+
),
33+
],
34+
)
35+
@logged_test
36+
def test_combination_sum(self, candidates: list[int], target: int, expected: list[list[int]]):
37+
result = self.solution.combination_sum(candidates, target)
38+
# Sort both result and expected for comparison
39+
result_sorted = [sorted(combo) for combo in result]
40+
expected_sorted = [sorted(combo) for combo in expected]
41+
result_sorted.sort()
42+
expected_sorted.sort()
43+
assert result_sorted == expected_sorted

leetcode/permutations/README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Permutations
2+
3+
**Difficulty:** Medium
4+
**Topics:** Array, Backtracking
5+
**Tags:** grind-75
6+
7+
**LeetCode:** [Problem 46](https://leetcode.com/problems/permutations/description/)
8+
9+
## Problem Description
10+
11+
Given an array `nums` of distinct integers, return all the possible permutations. You can return the answer in any order.
12+
13+
## Examples
14+
15+
### Example 1:
16+
17+
```
18+
Input: nums = [1,2,3]
19+
Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
20+
```
21+
22+
### Example 2:
23+
24+
```
25+
Input: nums = [0,1]
26+
Output: [[0,1],[1,0]]
27+
```
28+
29+
### Example 3:
30+
31+
```
32+
Input: nums = [1]
33+
Output: [[1]]
34+
```
35+
36+
## Constraints
37+
38+
- 1 <= nums.length <= 6
39+
- -10 <= nums[i] <= 10
40+
- All the integers of nums are unique.

leetcode/permutations/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)