Given a set of distinct positive integers nums
, return the largest subset answer
such that every pair (answer[i], answer[j])
of elements in this subset satisfies:
answer[i] % answer[j] == 0
, oranswer[j] % answer[i] == 0
If there are multiple solutions, return any of them.
For example:
nums = [1,2,3]
Possible outputs are [1,2]
or [1,3]
.
As another example:
nums = [1,2,4,8]
The only possible output is [1,2,4,8]
.
Describe an algorithm to find the largest divisible subset. What is the time and space complexity of your solution? What are the edge cases to consider? Provide code for your solution.
A naive approach would be to generate all possible subsets of the input array nums
and then check if each subset satisfies the given condition. We iterate through all subsets, and for each subset, we check every pair of elements to see if they meet the divisibility requirement. The largest subset that satisfies the condition is the answer.
Code (Python):
def largest_divisible_subset_brute_force(nums):
def check_subset(subset):
for i in range(len(subset)):
for j in range(i + 1, len(subset)):
if not (subset[i] % subset[j] == 0 or subset[j] % subset[i] == 0):
return False
return True
from itertools import combinations
largest_subset = []
for i in range(1, len(nums) + 1):
for subset in combinations(nums, i):
subset = list(subset)
if check_subset(subset):
if len(subset) > len(largest_subset):
largest_subset = subset
return largest_subset
Time Complexity: O(2n * n2), where n is the number of elements in nums
. Generating all subsets takes O(2n) time, and checking each subset for the divisibility condition takes O(n2) time in the worst case.
Space Complexity: O(n), primarily due to the space used to store the subsets.
A more efficient approach uses dynamic programming. First, sort the input array nums
. Then, create two arrays: dp
and predecessor
, both of the same length as nums
. dp[i]
stores the length of the largest divisible subset ending at nums[i]
. predecessor[i]
stores the index of the preceding element in the largest divisible subset ending at nums[i]
. Iterate through the sorted nums
, and for each nums[i]
, iterate through the preceding elements nums[j]
(where j < i
). If nums[i]
is divisible by nums[j]
, it means we can extend the divisible subset ending at nums[j]
by adding nums[i]
. Update dp[i]
and predecessor[i]
accordingly. After filling the dp
and predecessor
arrays, find the index with the maximum value in dp
. Backtrack from that index using the predecessor
array to construct the largest divisible subset.
Code (Python):
def largest_divisible_subset(nums):
nums.sort()
n = len(nums)
dp = [1] * n
predecessor = [-1] * n
max_index = 0
for i in range(n):
for j in range(i):
if nums[i] % nums[j] == 0:
if dp[i] < dp[j] + 1:
dp[i] = dp[j] + 1
predecessor[i] = j
if dp[i] > dp[max_index]:
max_index = i
result = []
curr = max_index
while curr != -1:
result.append(nums[curr])
curr = predecessor[curr]
return result
Time Complexity: O(n2), where n is the number of elements in nums
. The nested loops iterate through all possible pairs of elements.
Space Complexity: O(n), for the dp
and predecessor
arrays, and the result
list.
Edge Cases: