From 87494f1fa1022368d154477bdc035fd01f9e4382 Mon Sep 17 00:00:00 2001 From: Parth <100679824+pa-kh039@users.noreply.github.com> Date: Thu, 5 Oct 2023 21:51:28 +0530 Subject: [PATCH] largest divisible subset (#9825) * largest divisible subset * minor tweaks * adding more test cases Co-authored-by: Christian Clauss * improving code for better readability Co-authored-by: Christian Clauss * update Co-authored-by: Christian Clauss * update Co-authored-by: Christian Clauss * [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 Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../largest_divisible_subset.py | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 dynamic_programming/largest_divisible_subset.py diff --git a/dynamic_programming/largest_divisible_subset.py b/dynamic_programming/largest_divisible_subset.py new file mode 100644 index 000000000..db38636e2 --- /dev/null +++ b/dynamic_programming/largest_divisible_subset.py @@ -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)}." + )