22Partition a set into two subsets such that the difference of subset sums is minimum
33"""
44
5+ from collections .abc import Iterable
56
6- def find_min (numbers : list [int ]) -> int :
7+
8+ def find_min (numbers : Iterable [int ]) -> int :
79 """
810 >>> find_min([1, 2, 3, 4, 5])
911 1
@@ -21,8 +23,6 @@ def find_min(numbers: list[int]) -> int:
2123 0
2224 >>> find_min([-1, -5, 5, 1])
2325 0
24- >>> find_min([-1, -5, 5, 1])
25- 0
2626 >>> find_min([9, 9, 9, 9, 9])
2727 9
2828 >>> find_min([1, 5, 10, 3])
@@ -32,42 +32,20 @@ def find_min(numbers: list[int]) -> int:
3232 >>> find_min(range(10, 0, -1))
3333 1
3434 >>> find_min([-1])
35- Traceback (most recent call last):
36- --
37- IndexError: list assignment index out of range
35+ 1
3836 >>> find_min([0, 0, 0, 1, 2, -4])
39- Traceback (most recent call last):
40- ...
41- IndexError: list assignment index out of range
37+ 1
4238 >>> find_min([-1, -5, -10, -3])
43- Traceback (most recent call last):
44- ...
45- IndexError: list assignment index out of range
39+ 1
4640 """
47- n = len (numbers )
48- s = sum (numbers )
49-
50- dp = [[False for x in range (s + 1 )] for y in range (n + 1 )]
51-
52- for i in range (n + 1 ):
53- dp [i ][0 ] = True
54-
55- for i in range (1 , s + 1 ):
56- dp [0 ][i ] = False
57-
58- for i in range (1 , n + 1 ):
59- for j in range (1 , s + 1 ):
60- dp [i ][j ] = dp [i - 1 ][j ]
61-
62- if numbers [i - 1 ] <= j :
63- dp [i ][j ] = dp [i ][j ] or dp [i - 1 ][j - numbers [i - 1 ]]
41+ total_sum = 0
42+ reachable_sums = {0 }
6443
65- for j in range (int (s / 2 ), - 1 , - 1 ):
66- if dp [n ][j ] is True :
67- diff = s - 2 * j
68- break
44+ for number in numbers :
45+ total_sum += number
46+ reachable_sums |= {reachable_sum + number for reachable_sum in reachable_sums }
6947
70- return diff
48+ return min ( abs ( total_sum - 2 * reachable_sum ) for reachable_sum in reachable_sums )
7149
7250
7351if __name__ == "__main__" :
0 commit comments