题目描述:
Given a set of distinct positive integers,
find the largest subset such that every pair (Si, Sj) of elements
in this subset satisfies: Si % Sj = 0 or Sj % Si = 0.
If there are multiple solutions, return any subset is fine.
Example 1:
nums: [1,2,3]
Result: [1,2] (of course, [1,3] will also be ok)
Example 2:
nums: [1,2,4,8]
Result: [1,2,4,8]
(给定一个不重复正整数集合,寻找最大子集,
使得子集中的任意一对元素 (Si, Sj) 均满足Si % Sj = 0或者Sj % Si = 0。
如果存在多种答案,返回其中之一即可。
测试用例如题目描述。)
思路:确定状态转移方程:dp[i] = max(dp[i], dp[j]+1)
先排序,因为肯定是大的除小的才能没有余数
遍历数组将每一个数与其之前的数相除,如果可以整除一个数那么就一定能整除可以被这个数所整除的所有数
public class Largest_Divisible_Subset {
public static List<Integer> largestDivisibleSubset(int[] nums)
{
List<Integer> result=new ArrayList<Integer>();
if(nums == null||nums.length == 0)
{
return result;
}
Arrays.sort(nums);
int max = 0;
int maxIndex = 0;
int dp[] = new int[nums.length];
int index[] = new int[nums.length];
//这里要对下标数组赋初值,因为后面对下标追踪时可能会到下标为零的数
//如果不赋初值那么在最后一个循环时,追踪到下标为零的数时,i=index[0]=0;此时判断条件是i>=0,会造成死循环
for(int i=0;i<index.length;i++){
index[i] = -1;
}
for(int i=1;i<nums.length;i++)
{
for(int j=0;j<i;j++)
{
if(nums[i]%nums[j]==0)
{
//虽然动态方程是dp[i] = max(dp[i], dp[j]+1)
//但不可以直接使用,因为这样只能记录每个点之前有多少符合条件的数却无法找到到底是哪些
//所以需要用数组追踪就可以
//而且只需记录一个数,因为如果可以整除一个数那么就一定能整除可以被这个数所整除的所有数
if(dp[i]<dp[j]+1)
{
dp[i] = dp[j]+1;
index[i] = j;
//这里是为了记录最大子串
if(dp[i]>max)
{
max = dp[i];
maxIndex = i;
}
}
}
}
}
for(int i=maxIndex;i>=0;i=index[i])
{
result.add(0,nums[i]);
}
return result;
}
public static void main(String[] args) {
int nums[] = {2,3,9,12,24};
List<Integer> result = largestDivisibleSubset(nums);
for(int i=0;i<result.size();i++)
{
System.out.print(result.get(i)+" ");
}
}
}