import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * 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. * <p> * If there are multiple solutions, return any subset is fine. * <p> * Example 1: * <p> * nums: [1,2,3] * <p> * Result: [1,2] (of course, [1,3] will also be ok) * Example 2: * <p> * nums: [1,2,4,8] * <p> * Result: [1,2,4,8] * <p> * Tags: Dynamic Programming, Math */ public class LargestDivisibleSubset { /** * For a new integer S, S can be placed into the set as long as it can divide the smallest number of the set or is * divisible by the largest number of the set. * <p> * Recurrent relation: * T[n] = the length of the largest divisible subset whose largest number is a[n] * T[n+1] = max{ 1 + T[i] } if a[n+1] mod a[i] == 0 for 0<=i<=n, else 1 * <p> * Sort the array first. * Create an array named parent to record parent index of current element. * Create an array named count to record the largest subset of current element. * Then Start from one end of the array and try to find larger element that divides current element. * If it divides and subset size is smaller than that element + 1, then update size and parent. * If count is bigger than max, update max and max index. * Finally, recover the list of integers with parent array. */ public List<Integer> largestDivisibleSubset(int[] nums) { if (nums == null) throw new NullPointerException("Input array nums is null"); if (nums.length <= 1) throw new IllegalArgumentException("Input array must have at least 2 elements"); Arrays.sort(nums); int[] parent = new int[nums.length]; int[] count = new int[nums.length]; int max = 0; int maxIndex = -1; for (int i = nums.length - 1; i >= 0; i--) { for (int j = i; j < nums.length; j++) { if (nums[j] % nums[i] == 0 && count[i] < 1 + count[j]) { count[i] = 1 + count[j]; parent[i] = j; if (count[i] > max) { max = count[i]; maxIndex = i; } } } } List<Integer> res = new ArrayList<>(); for (int i = 0; i < max; i++) { res.add(nums[maxIndex]); maxIndex = parent[maxIndex]; } return res; } }