- 最大整除子集 难度[中等]
给你一个由 无重复 正整数组成的集合 nums ,请你找出并返回其中最大的整除子集 answer ,子集中每一元素对 (answer[i], answer[j]) 都应当满足:
- answer[i] % answer[j] == 0 ,或
如果存在多个有效解子集,返回其中任何一个均可。
示例 1:
输入:nums = [1,2,3]
输出:[1,2]
解释:[1,3] 也会被视为正确答案。
示例 2:
输入:nums = [1,2,4,8]
输出:[1,2,4,8]
提示:
- 1 <= nums.length <= 1000
- 1 <= nums[i] <= 2 * 10^9
- nums 中的所有整数 互不相同
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/largest-divisible-subset
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法:动态规划
状态定义 f[i]: 到 i 位置 位置 最长的子集长度
public List<Integer> largestDivisibleSubset(int[] nums) {
Arrays.sort(nums);
int n= nums.length;
//f[i]: 到位置 i 上 最长的子集长度
int [] f = new int [n];
//记录 f[i] 是由哪个下标的状态转移而来
int [] g = new int [n];
for(int i =0;i<n ;i++){
//保证至少包含自身一个数
int len =1,prev=i;
for(int j=0;j<=i;j++){
//判断是否能接在最长子集的后面
if(nums[i]%nums[j]==0){
//更新 最大长度 和 从何转移过来
if(f[j]+1>len){
len=f[j]+1;
prev=j;
}
}
}
//记录 最长的子集长度 和 最长子集的最后一个数从何转移过来
f[i]=len;
g[i]=prev;
}
//找到最长子集 和 最长子集的最后一个数从何转移过来
int max =-1,idx=-1;
for(int i=0;i<n;i++){
if(f[i]>max){
max=f[i];
idx=i;
}
}
//通过 g[idx]来回溯 最长子集
List<Integer> list = new ArrayList<>();
while (list.size()<max){
list.add(nums[idx]);
idx=g[idx];
}
return list;
}
参考 【宫水三叶の相信科学系列】详解为何能转换为序列 DP 问题
此文章创于本人学习时的记录,如有错误或更优解还请指出