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]
should return [1,2]
(or [1,3]
, either is fine).
nums = [1,2,4,8]
should return [1,2,4,8]
.
How would you approach this problem? Consider edge cases and optimize for time and space complexity.
Let's discuss how to find the largest divisible subset from a given set of distinct positive integers.
A straightforward, but inefficient, approach is to generate all possible subsets and check if each subset satisfies the divisibility condition. We keep track of the largest subset found so far that meets the criteria.
answer[i] % answer[j] == 0
or answer[j] % answer[i] == 0
.Code (Python):
def get_all_subsets(nums):
subsets = [[]]
for num in nums:
new_subsets = [subset + [num] for subset in subsets]
subsets.extend(new_subsets)
return subsets
def check_divisibility(subset):
if not subset:
return True
for i in range(len(subset)):
for j in range(i + 1, len(subset)):
if subset[i] % subset[j] != 0 and subset[j] % subset[i] != 0:
return False
return True
def largest_divisible_subset_brute_force(nums):
all_subsets = get_all_subsets(nums)
largest_subset = []
for subset in all_subsets:
if check_divisibility(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 divisibility takes O(n2) time.
Space Complexity: O(2n * n) in the worst case to store all subsets.
To solve this problem efficiently, we can use dynamic programming.
nums
in ascending order. Sorting allows us to only check divisibility in one direction (smaller to larger).dp[i]
stores the size of the largest divisible subset ending at nums[i]
.pre[i]
stores the index of the previous element in the largest divisible subset ending at nums[i]
.dp[i]
is initialized to 1, and each pre[i]
is initialized to i
.nums[i]
, iterate through all 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]
.
dp[j] + 1 > dp[i]
, update dp[i]
to dp[j] + 1
and pre[i]
to j
.dp
value: This index represents the end of the largest divisible subset.dp
value, backtrack using the pre
array to reconstruct the largest divisible subset.Code (Python):
def largest_divisible_subset(nums):
n = len(nums)
nums.sort()
dp = [1] * n
pre = list(range(n))
max_len = 1
max_index = 0
for i in range(1, n):
for j in range(i):
if nums[i] % nums[j] == 0:
if dp[j] + 1 > dp[i]:
dp[i] = dp[j] + 1
pre[i] = j
if dp[i] > max_len:
max_len = dp[i]
max_index = i
result = []
curr = max_index
while curr != pre[curr]:
result.append(nums[curr])
curr = pre[curr]
result.append(nums[curr])
return result
Time Complexity: O(n2), where n is the number of elements in nums
. The nested loops dominate the runtime.
Space Complexity: O(n) to store the dp
and pre
arrays, as well as the result.
By using dynamic programming, we significantly improve the efficiency compared to the brute-force approach.