Skip to content

Commit c4376ca

Browse files
author
Yuva
authored
Update combination_sum.py
Here is the updated and clearer version of the code with improved readability, type annotations, and error handling for invalid inputs.
1 parent 0bcdfbd commit c4376ca

File tree

1 file changed

+64
-33
lines changed

1 file changed

+64
-33
lines changed

backtracking/combination_sum.py

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,97 @@
1-
"""
2-
In the Combination Sum problem, we are given a list consisting of distinct integers.
3-
We need to find all the combinations whose sum equals to target given.
4-
We can use an element more than one.
1+
"""
2+
Combination Sum Problem
53
6-
Time complexity(Average Case): O(n!)
4+
Description:
5+
Given a list of distinct integers (candidates), find all unique combinations where the sum of elements equals the given target.
6+
An element can be used multiple times in a combination.
77
88
Constraints:
99
1 <= candidates.length <= 30
1010
2 <= candidates[i] <= 40
1111
All elements of candidates are distinct.
1212
1 <= target <= 40
13-
"""
1413
14+
Time complexity (Average Case): O(n!)
15+
"""
1516

1617
def backtrack(
17-
candidates: list, path: list, answer: list, target: int, previous_index: int
18+
candidates: list[int],
19+
path: list[int],
20+
answer: list[list[int]],
21+
target: int,
22+
start_index: int
1823
) -> None:
1924
"""
20-
A recursive function that searches for possible combinations. Backtracks in case
21-
of a bigger current combination value than the target value.
25+
Recursive helper function to find all valid combinations.
2226
23-
Parameters
27+
Parameters:
2428
----------
25-
previous_index: Last index from the previous search
26-
target: The value we need to obtain by summing our integers in the path list.
27-
answer: A list of possible combinations
28-
path: Current combination
29-
candidates: A list of integers we can use.
29+
candidates : list[int]
30+
A list of distinct integers we can use to form combinations.
31+
path : list[int]
32+
The current combination being formed.
33+
answer : list[list[int]]
34+
The list of valid combinations that sum to the target.
35+
target : int
36+
The remaining sum needed to reach the target.
37+
start_index : int
38+
The index to start searching from in the candidates list.
39+
40+
Returns:
41+
-------
42+
None
3043
"""
3144
if target == 0:
3245
answer.append(path.copy())
33-
else:
34-
for index in range(previous_index, len(candidates)):
35-
if target >= candidates[index]:
36-
path.append(candidates[index])
37-
backtrack(candidates, path, answer, target - candidates[index], index)
38-
path.pop(len(path) - 1)
46+
return
3947

48+
for i in range(start_index, len(candidates)):
49+
if candidates[i] <= target:
50+
path.append(candidates[i])
51+
backtrack(candidates, path, answer, target - candidates[i], i) # Same index for reuse
52+
path.pop() # Backtrack
4053

41-
def combination_sum(candidates: list, target: int) -> list:
54+
def combination_sum(candidates: list[int], target: int) -> list[list[int]]:
4255
"""
56+
Finds all unique combinations of candidates that sum up to the target.
57+
58+
Parameters:
59+
----------
60+
candidates : list[int]
61+
A list of distinct integers.
62+
target : int
63+
The target sum we want to achieve.
64+
65+
Returns:
66+
-------
67+
list[list[int]]
68+
A list of all unique combinations.
69+
70+
Examples:
71+
--------
4372
>>> combination_sum([2, 3, 5], 8)
4473
[[2, 2, 2, 2], [2, 3, 3], [3, 5]]
4574
>>> combination_sum([2, 3, 6, 7], 7)
4675
[[2, 2, 3], [7]]
47-
>>> combination_sum([-8, 2.3, 0], 1)
48-
Traceback (most recent call last):
49-
...
50-
RecursionError: maximum recursion depth exceeded
76+
>>> combination_sum([], 7)
77+
[]
78+
>>> combination_sum([1], 0)
79+
[]
5180
"""
52-
path = [] # type: list[int]
53-
answer = [] # type: list[int]
54-
backtrack(candidates, path, answer, target, 0)
55-
return answer
81+
if not candidates or target <= 0:
82+
return []
5683

84+
answer: list[list[int]] = []
85+
backtrack(candidates, [], answer, target, 0)
86+
return answer
5787

5888
def main() -> None:
59-
print(combination_sum([-8, 2.3, 0], 1))
60-
89+
"""Main function to test the combination_sum function."""
90+
print("Example 1:", combination_sum([2, 3, 5], 8))
91+
print("Example 2:", combination_sum([2, 3, 6, 7], 7))
92+
print("Example 3 (Invalid input):", combination_sum([], 1)) # Should return []
6193

6294
if __name__ == "__main__":
6395
import doctest
64-
6596
doctest.testmod()
6697
main()

0 commit comments

Comments
 (0)