LeetCode Largest Divisible Subset

368. Largest Divisible Subset

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]

方法

一开始上来这个题目直观的就是使用动态规划,可是在集合中判断两两是否模为0,可能两个数位置相差很大,很难找到状态转换方程。找到转换方程的诀窍就是,对集合由大到小排序,因为若a%b=0,b%c=0 ==> a%c=0,排序后可以保证若当前数与前一某个数能取模为0,那么他可以满足与那个数的所有符合取模为0的数取模为0。即找到状态转换方程,dp[i]表示在i点上能与之前的数互相取模的最大数量:

dp[i] = max(dp[i],dp[j]+1),(j<i,num[i]%num[j]==0)

同时该题目又要求打印所有节点,所以还需要另外一个一维数组,存储在位置i的前一个满足num[i]%num[j]==0的地址,所以实际上该题也可以使用二维数组,一起存储dp[]和pre[],最后根据pre[i]的地址打印,此题result==dp,result[i]初始都为1,pre[i]初始都为-1

谨记

在此题中,最后一个数并不代表它与其他数取模的个数最多如{2,4,8,11},11并不能与其他数取余,所以还需要每次遍历时判断max和maxIndex,pre[i]从maxIndex开始出发。

public class Solution {
    public List<Integer> largestDivisibleSubset(int[] nums) {
        int length = nums.length;
        Arrays.sort(nums);
        int[] result = new int[length];
        List<Integer> res = new ArrayList<Integer>();
        int[] pre = new int[length];
        int max = 0;
        int maxIndex = -1;
        for(int i = 0; i < length; i++){
            result[i] = 1;
            pre[i] = -1;
            for(int j = i-1; j >= 0; j--){
                if(nums[i]%nums[j] == 0){
                    if(result[j] + 1 > result[i]){
                        result[i] = result[j]+1;
                        pre[i] = j;
                    }
                }
            }
            if(result[i] > max){
                max = result[i];
                maxIndex = i;
            }
        }
        while(maxIndex != -1){
            res.add(nums[maxIndex]);
            maxIndex = pre[maxIndex];
        }
        return res;
    }
}
Share