zoukankan      html  css  js  c++  java
  • 最大整除子集

    给出一个由无重复的正整数组成的集合,找出其中最大的整除子集,子集中任意一对 (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;
        
        }
    }
  • 相关阅读:
    进程、线程
    timer控件、三级联动
    用户控件、动态创建添加
    打印控件
    窗体移动和阴影,对话框控件
    winform listview控件
    winform打开唯一窗体、构造函数传值
    菜单和工具栏
    winform公共控件
    hibernate中各种包的添加
  • 原文地址:https://www.cnblogs.com/du001011/p/10817185.html
Copyright © 2011-2022 走看看