码迷,mamicode.com
首页 > 其他好文 > 详细

最大整除子集

时间:2019-05-06 01:40:13      阅读:261      评论:0      收藏:0      [点我收藏+]

标签:[]   排序   ==   arraylist   list   例子   规划   最大的   lis   

给出一个由无重复的正整数组成的集合,找出其中最大的整除子集,子集中任意一对 (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]

这道题和找最长子序列有点像!

  1. 排序
  2. 动态规划找到最长的整除子集,但是要记录前一个数位置

举个例子 [1,2,3]

我们用dp[i]记录到i最长的整除子集长度,用pre[i]记录到i前面一个数的位置

很明显dp[0] = 1 ,pre[0] = -1

当i = 1,有nums[1] % nums[0] == 0可以整除,如果dp[0] + 1 > dp[1],那么pre[1] = 0,dp[1] = 2

当i = 2,也有有nums[2] % nums[0] == 0可以整除,那么我们判断i=2之前可以整除的,有nums[2] % nums[1] != 0,所以有nums[2] % nums[0] == 0能整除,有dp[0] + 1 > dp[2],

那么pre[2] = 0,dp[1] = 2

接下来我们就取dp最大值,即最长的整除子集长度,再根据记录的前面数的位置找出所有的数字

public List<Integer> largestDivisibleSubset(int[] nums) {
       int len = nums.length, m = 0, mi = 0;
        int[] dp = new int[len];
        int[] prev = new int[len];

        Arrays.sort(nums);

        for (int i = 0; i < len; i++) {
            for (int j = i; j >= 0; j--) {
                if (nums[i] % nums[j] == 0 && dp[j] + 1 > dp[i]) {
                    dp[i] = dp[j] + 1;
                    prev[i] = j;
                }
            }
            if (dp[i] > m) {
                m = dp[i];
                mi = i;
            }
        }

        List<Integer> res = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            res.add(nums[mi]);
            mi = prev[mi];
        }

        return res;
    
    }
}

 

最大整除子集

标签:[]   排序   ==   arraylist   list   例子   规划   最大的   lis   

原文地址:https://www.cnblogs.com/du001011/p/10817185.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!