Problem Statement
(Source) Given a set of distinct positive integers, find the largest subset such that every pair (Si, Sj) of elements in this subset satisfies: Si % Sj = 0 or Sj % Si = 0.
If there are multiple solutions, return any subset is fine.
Example 1:
nums: [1,2,3] Result: [1,2] (of course, [1,3] will also be ok)
Example 2:
nums: [1,2,4,8] Result: [1,2,4,8]
Solution 1
My S[x] is the largest subset with x as the largest element, i.e., the subset of all divisors of x in the input. With S[1] = “empty set” as useful base case. Since divisibility is transitive, a multiple x of some divisor d is also a multiple of all elements in S[d], so it’s not necessary to explicitly test divisibility of x by all elements in S[d]. Testing x % d suffices.
While storing entire subsets isn’t super efficient, it’s also not that bad. To extend a subset, the new element must be divisible by all elements in it, meaning it must be at least twice as large as the largest element in it. So with the 31-bit integers we have here, the largest possible set has size 31 (containing all powers of 2).
class Solution(object):
def largestDivisibleSubset(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
s = {1 : set()}
for x in sorted(nums):
s[x] = max([s[i] for i in s if x % i == 0], key=len) | {x}
return list(max(s.values(), key=len))
Solution 2
Using Dynamic Programming
.
class Solution(object):
def largestDivisibleSubset(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
if not nums:
return []
nums.sort()
n = len(nums)
ans = 0
index = 0
dp = [(1, i) for i in xrange(n)]
for i in xrange(n - 1, -1, -1):
for j in xrange(i + 1, n):
if nums[j] % nums[i] == 0 and dp[j][0] + 1 > dp[i][0]:
dp[i] = (dp[j][0] + 1, j)
if ans < dp[i][0]:
ans = dp[i][0]
index = i
rtn = [nums[index]]
while dp[index][1] != index:
rtn.append(nums[dp[index][1]])
index = dp[index][1]
return rtn
References
[1] https://discuss.leetcode.com/topic/49455/4-lines-in-python