Skip to content

Commit

Permalink
largest divisible subset (#9825)
Browse files Browse the repository at this point in the history
* largest divisible subset

* minor tweaks

* adding more test cases

Co-authored-by: Christian Clauss <[email protected]>

* improving code for better readability

Co-authored-by: Christian Clauss <[email protected]>

* update

Co-authored-by: Christian Clauss <[email protected]>

* update

Co-authored-by: Christian Clauss <[email protected]>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* suggested changes done, and further modfications

* final update

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update largest_divisible_subset.py

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update largest_divisible_subset.py

---------

Co-authored-by: Christian Clauss <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people committed Oct 5, 2023
1 parent deb0480 commit 87494f1
Showing 1 changed file with 74 additions and 0 deletions.
74 changes: 74 additions & 0 deletions dynamic_programming/largest_divisible_subset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from __future__ import annotations


def largest_divisible_subset(items: list[int]) -> list[int]:
"""
Algorithm to find the biggest subset in the given array such that for any 2 elements
x and y in the subset, either x divides y or y divides x.
>>> largest_divisible_subset([1, 16, 7, 8, 4])
[16, 8, 4, 1]
>>> largest_divisible_subset([1, 2, 3])
[2, 1]
>>> largest_divisible_subset([-1, -2, -3])
[-3]
>>> largest_divisible_subset([1, 2, 4, 8])
[8, 4, 2, 1]
>>> largest_divisible_subset((1, 2, 4, 8))
[8, 4, 2, 1]
>>> largest_divisible_subset([1, 1, 1])
[1, 1, 1]
>>> largest_divisible_subset([0, 0, 0])
[0, 0, 0]
>>> largest_divisible_subset([-1, -1, -1])
[-1, -1, -1]
>>> largest_divisible_subset([])
[]
"""
# Sort the array in ascending order as the sequence does not matter we only have to
# pick up a subset.
items = sorted(items)

number_of_items = len(items)

# Initialize memo with 1s and hash with increasing numbers
memo = [1] * number_of_items
hash_array = list(range(number_of_items))

# Iterate through the array
for i, item in enumerate(items):
for prev_index in range(i):
if ((items[prev_index] != 0 and item % items[prev_index]) == 0) and (
(1 + memo[prev_index]) > memo[i]
):
memo[i] = 1 + memo[prev_index]
hash_array[i] = prev_index

ans = -1
last_index = -1

# Find the maximum length and its corresponding index
for i, memo_item in enumerate(memo):
if memo_item > ans:
ans = memo_item
last_index = i

# Reconstruct the divisible subset
if last_index == -1:
return []
result = [items[last_index]]
while hash_array[last_index] != last_index:
last_index = hash_array[last_index]
result.append(items[last_index])

return result


if __name__ == "__main__":
from doctest import testmod

testmod()

items = [1, 16, 7, 8, 4]
print(
f"The longest divisible subset of {items} is {largest_divisible_subset(items)}."
)

0 comments on commit 87494f1

Please sign in to comment.