Skip to content

Commit db9fb38

Browse files
committed
adding algo
1 parent 6e3d42e commit db9fb38

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from typing import List, Union, Collection, Mapping, Optional
2+
from collections import defaultdict
3+
4+
class Solution:
5+
def countTheNumOfKFreeSubsets(self, nums: List[int], k: int) -> int:
6+
"""
7+
Count k-Free subsets using dynamic programming.
8+
9+
Approach:
10+
1. Group elements by (num % k) to find independent groups
11+
2. Within each group, sort and build chains where elements differ by k
12+
3. For each chain, use House Robber DP to count valid subsets
13+
4. Multiply results across all independent chains
14+
15+
Time: O(n log n), Space: O(n)
16+
"""
17+
# Group numbers by their remainder when divided by k
18+
groups = defaultdict(list)
19+
for num in nums:
20+
groups[num % k].append(num)
21+
22+
res = 1
23+
24+
# Process each group independently
25+
for group in groups.values():
26+
group.sort()
27+
28+
# Build chains within this group
29+
i = 0
30+
while i < len(group):
31+
chain = [group[i]]
32+
j = i + 1
33+
34+
# Build chain where each element is exactly k more than previous
35+
while j < len(group) and group[j] == chain[-1] + k:
36+
chain.append(group[j])
37+
j += 1
38+
39+
# House Robber DP for this chain
40+
m = len(chain)
41+
if m == 1:
42+
chain_res = 2 # {} or {chain[0]}
43+
else:
44+
take = 1 # Take first element
45+
skip = 1 # Skip first element
46+
47+
for idx in range(1, m):
48+
new_take = skip # Can only take current if we skipped previous
49+
new_skip = take + skip # Can skip current regardless
50+
take, skip = new_take, new_skip
51+
52+
chain_res = take + skip
53+
54+
res *= chain_res
55+
i = j
56+
57+
return res

0 commit comments

Comments
 (0)