最大整除子集
给出一个由无重复的正整数组成的集合,找出其中最大的整除子集,子集中任意一对 (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]
解题分析:
如果a%b==0,则a=mb,所以如果把数组排序后如果a%b==0,且b%c==0则a%c==0。这就为用动态规划实现提供了可能性。设置一个数组result,result[i]表示i出包含的满足条件的子集个数。则如果nums[i]%nums[j]==0,则result[i]=result[j]+1;同时由于函数要返回的是一个List,所以我们要保存最长集合的路径。这个功能可以通过设置一个pre数组保存能被nums[i]整除的上一个数的索引。并在保存max值的同时保存max所在的位置maxIndex即可。
1 import java.util.*; 2 3 class Solution { 4 public static List<Integer> largestDivisibleSubset(int[] nums) { 5 List<Integer> result=new ArrayList<Integer>(); 6 List<Integer> numsList=new ArrayList<Integer>(); 7 for(int i=0;i<nums.length;i++){ 8 numsList.add(nums[i]); 9 } 10 if(nums.length==0) return result; 11 Collections.sort(numsList,Collections.reverseOrder()); 12 int len=numsList.size(); 13 int curMax=1; 14 int k=0; 15 int[] par=new int[len]; 16 int[] dp=new int[len]; 17 Arrays.fill(dp,1); 18 for(int i=0;i<len;i++){ 19 par[i]=i; 20 } 21 for(int i=1;i<len;i++){ 22 for(int j=0;j<i;j++){ 23 if(numsList.get(j)%numsList.get(i)!=0){ 24 continue; 25 } 26 if(dp[i]<dp[j]+1){ 27 par[i]=j; 28 dp[i]=dp[j]+1; 29 } 30 if(dp[i]>curMax){ 31 curMax=dp[i]; 32 k=i; 33 } 34 } 35 } 36 while(par[k]!=k){ 37 result.add(numsList.get(k)); 38 k=par[k]; 39 } 40 result.add(numsList.get(k)); 41 return result; 42 } 43 }