368 Largest Divisible Subset
压缩DP的题型, 且state transition function依赖于多个前驱节点,且prior nodes需要通过题目条件,也就是nums[i] % nums[j] == 0 or nums[j] % nums[i] ==0 来进行筛选.
Approach 1 DP bottom-up, \(O(N^2)\) time, \(O(N)\) space
最重要的思路是,转换, nums[i] % nums[j] == 0 or nums[j] % nums[i] ==0 可以等价于nums[i] % nums[j] == 0 and i > j, 这一题目正好满足这个条件, 因为每个数字都是unique的
1 <= nums.length <= 1000
1 <= nums[i] <= 2 * 109
All the integers in nums are unique.
Tip
如果nums中的数字不是unique的,可以构建个hashmap记录每个数字出现的occurrence, 最后max(dp)加上就可以了.
dp definition
dp[i]:
the length of the largest divisible subset ending at i elment
in the ascendingly sorted input array.
prev[i]:
the previous index of the largest divisible subset ending at i element. 这个array的value指向的是上一个index that is divisible by nums[i]
注意,这并不是我们要求的,我们要求的是任一符合条件的largest divisible subset, 但是这个dp数组可以帮助我们找到最大的index, 然后我们可以通过prev数组回溯找到最大的subset.

initial condition
dp[i] = 1 for all
state transition function
if nums[i] % nums[j] == 0:
dp[i] = max(dp[i], 1 + dp[j])
if dp[j]+1 == dp[i]:
prev[i] = j
- 更新dp[i]
prev[i]的更新记录了nums[i]的previous index, 这个数的previous index为nums[j]
代码如下:
class Solution:
def largestDivisibleSubset(self, nums: List[int]) -> List[int]:
# largest subset, every num % 1 == 0
# dp[i]:
# the length of the largest divisible subset ending at i elment
# in the ascendingly sorted input array.
# initial conditon:
# dp[i] = 1 for all, dp[0] = 0
# state transition function
# dp[i] = max(dp[i], 1 + dp[j])
# prev[i] = j, 这个数的previous index为
nums.sort()
dp = [1 for _ in range(len(nums))]
prev = [-1 for _ in range(len(nums))]
for i in range(len(nums)):
for j in range(0,i):
if nums[i] % nums[j] == 0:
dp[i] = max(dp[i], 1 + dp[j])
# successfully updated
if dp[j]+1 == dp[i]:
prev[i] = j
# find the max index
max_length = -1
max_index = -1
for i,length in enumerate(dp):
if length > max_length:
max_length = length
max_index = i
# now we have the max index,
# largest divisible subset will be ending at element nums[i] where nums is sorted
# we need to brack track until we find the res
res = []
while max_index != -1:
res.append(nums[max_index])
max_index = prev[max_index]
return res