给出一个由无重复的正整数组成的集合,找出其中最大的整除子集,子集中任意一对 (Si,Sj) 都要满足:Si % Sj = 0 或 Sj % Si = 0。
如果有多个目标子集,返回其中任何一个均可。
示例 1:
输入: [1,2,3] 输出: [1,2] (当然, [1,3] 也正确)
示例 2:
输入: [1,2,4,8] 输出: [1,2,4,8]
这道题和找最长子序列有点像!
- 排序
- 动态规划找到最长的整除子集,但是要记录前一个数位置
举个例子 [1,2,3]
我们用dp[i]记录到i最长的整除子集长度,用pre[i]记录到i前面一个数的位置
很明显dp[0] = 1 ,pre[0] = -1
当i = 1,有nums[1] % nums[0] == 0可以整除,如果dp[0] + 1 > dp[1],那么pre[1] = 0,dp[1] = 2
当i = 2,也有有nums[2] % nums[0] == 0可以整除,那么我们判断i=2之前可以整除的,有nums[2] % nums[1] != 0,所以有nums[2] % nums[0] == 0能整除,有dp[0] + 1 > dp[2],
那么pre[2] = 0,dp[1] = 2
接下来我们就取dp最大值,即最长的整除子集长度,再根据记录的前面数的位置找出所有的数字
public List<Integer> largestDivisibleSubset(int[] nums) { int len = nums.length, m = 0, mi = 0; int[] dp = new int[len]; int[] prev = new int[len]; Arrays.sort(nums); for (int i = 0; i < len; i++) { for (int j = i; j >= 0; j--) { if (nums[i] % nums[j] == 0 && dp[j] + 1 > dp[i]) { dp[i] = dp[j] + 1; prev[i] = j; } } if (dp[i] > m) { m = dp[i]; mi = i; } } List<Integer> res = new ArrayList<>(); for (int i = 0; i < m; i++) { res.add(nums[mi]); mi = prev[mi]; } return res; } }