-
Notifications
You must be signed in to change notification settings - Fork 0
/
alg_count_subset_sum.py
114 lines (83 loc) · 2.76 KB
/
alg_count_subset_sum.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
def count_subset_sum_recur(arr, total, n):
"""Count subsets given sum by recusrion.
Time complexity: O(2^n), where n is length of array.
Space complexity: O(1).
"""
if total < 0:
return 0
if total == 0:
return 1
if n < 0:
return 0
if total < arr[n]:
return count_subset_sum_recur(arr, total, n - 1)
else:
n_subsets_in = count_subset_sum_recur(arr, total - arr[n], n - 1)
n_subsets_out = count_subset_sum_recur(arr, total, n - 1)
return n_subsets_in + n_subsets_out
def _count_subset_sum_memo(arr, total, n, T):
"""Helper function for count_subsets_total_memo()."""
if total < 0:
return 0
if total == 0:
return 1
if n < 0:
return 0
if T[n][total]:
return T[n][total]
if total < arr[n]:
n_subsets = _count_subset_sum_memo(arr, total, n - 1, T)
else:
n_subsets_in = _count_subset_sum_memo(arr, total - arr[n], n - 1, T)
n_subsets_out = _count_subset_sum_memo(arr, total, n - 1, T)
n_subsets = n_subsets_in + n_subsets_out
T[n][total] = n_subsets
return n_subsets
def count_subset_sum_memo(arr, total):
"""Count subsets given sum by top-down memoization.
Time complexity: O(nm), where n is length of array, and m is total.
Space complexity: O(nm).
"""
n = len(arr) - 1
T = [[0] * (total + 1) for _ in range(n + 1)]
for a in range(n):
T[a][0] = 1
return _count_subset_sum_memo(arr, total, n, T)
def count_subset_sum_dp(arr, total):
"""Count subsets given sum by bottom-up dynamic programming.
Time complexity: O(nm).
Space complexity: O(nm).
"""
n = len(arr) - 1
T = [[0] * (total + 1) for _ in range(n + 1)]
for a in range(n + 1):
T[a][0] = 1
for a in range(n + 1):
for t in range(1, total + 1):
if t < arr[a]:
T[a][t] = T[a - 1][t]
else:
T[a][t] = T[a - 1][t] + T[a - 1][t - arr[a]]
return T[-1][-1]
def main():
import time
arr = [2, 4, 6, 10]
total = 16
n = len(arr) - 1
start_time = time.time()
n_subsets = count_subset_sum_recur(arr, total, n)
print('Recursion: {}'.format(n_subsets))
print('Time: {}'.format(time.time() - start_time))
start_time = time.time()
n_subsets = count_subset_sum_memo(arr, total)
print('Memo: {}'.format(n_subsets))
print('Time: {}'.format(time.time() - start_time))
start_time = time.time()
n_subsets = count_subset_sum_dp(arr, total)
print('DP: {}'.format(n_subsets))
print('Time: {}'.format(time.time() - start_time))
if __name__ == '__main__':
main()