问题背景
给你一个由 无重复 正整数组成的集合 n u m s nums nums,请你找出并返回其中最大的整除子集 a n s w e r answer answer,子集中每一元素对 ( a n s w e r [ i ] , a n s w e r [ j ] ) (answer[i], answer[j]) (answer[i],answer[j]) 都应当满足:
- a n s w e r [ i ] % a n s w e r [ j ] = 0 answer[i] \ \% \ answer[j] = 0 answer[i] % answer[j]=0,或
- a n s w e r [ j ] % a n s w e r [ i ] = 0 answer[j] \ \% \ answer[i] = 0 answer[j] % answer[i]=0
如果存在多个有效解子集,返回其中任何一个均可。
数据约束
- 1 ≤ n u m s . l e n g t h ≤ 1000 1 \le nums.length \le 1000 1≤nums.length≤1000
- 1 ≤ n u m s [ i ] ≤ 2 × 1 0 9 1 \le nums[i] \le 2 \times 10 ^ 9 1≤nums[i]≤2×109
- n u m s nums nums 中的所有整数 互不相同
解题过程
生成答案的过程,应当是在已经形成的子集中尝试添加新元素,最终结果是从规模更小的解转移而来,用动态规划解决,类似 最长递增子序列。
具体实现
class Solution {public List<Integer> largestDivisibleSubset(int[] nums) {Arrays.sort(nums);int n = nums.length;int[] memo = new int[n];int[] from = new int[n];Arrays.fill(from, -1);int res = 0;int index = 0;for (int i = 0; i < n; i++) {int cur = dfs(i, nums, memo, from);if (cur > res) {res = cur;index = i;}}List<Integer> path = new ArrayList<>(res);for (int i = index; i >= 0; i = from[i]) {path.add(nums[i]);}return path;}private int dfs(int i, int[] nums, int[] memo, int[] from) {if (memo[i] > 0) {return memo[i];}int res = 0;for (int j = 0; j < i; j++) {if (nums[i] % nums[j] != 0) {continue;}int cur = dfs(j, nums, memo, from);if (cur > res) {res = cur;from[i] = j;}}return memo[i] = res + 1;}
}