动态规划之 368Largest Divisible Subset

这是一篇关于使用动态规划解决LeetCode上的368题——寻找最大的互余子集的问题。文章介绍了如何对数组排序,并通过比较数组元素间的互余关系来找到符合条件的子数组。示例中给出了[1,2,3]和[1,2,4,8]两个例子,说明解题思路和解决方案。" 105016963,9389736,C++解决青蛙跳台阶问题,"['动态规划', '算法', 'C++']

这是leetcode上的关于动态规划的一道题,先来看下原题:
368. Largest Divisible Subset QuestionEditorial Solution My Submissions
Total Accepted: 3593
Total Submissions: 12097
Difficulty: Medium
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]

要求子数组里任何两个元素均要满足互余。这道题看起来好像有点复杂,但是解题的思路很直接。最方便的做法是先对数组进行排序。然后比较nums[i]与nums[j]是否互余:
if nums[i] % nums[j] = 0 then leng[i] = leng[j] + 1
leng[i]表示的是到i这个位置时,满足条件的子数组长度。
下面给出两种方法,思路是一样的。不同的是借助的数据结构不同:第一种方法利用List

public List<Integer> largestDivisibleSubset1(int[] a) {
        List<List<Integer>> list = new ArrayList<List<Integer>>();
        if(a.length < 1) return new ArrayList<Integer>();
        int max = 0;
        int p = 0;
        for(int k = 0; k < a.length; k++){
            list.add(k, new ArrayList<Integer>());
        }

        if(a.length >= 1){
            Arrays.sort(a);
            int[] leng = new int[a.length];
            int j = 0;
            for(int i = 0; i < a.length; i++){
                for(j = i - 1; j >= 0; j--){
                    if(a[i] % a[j] == 0 && a[i] > a[j]){
                        if(leng[i] < leng[j] + 1){
                            leng[i] = leng[j] + 1;
                            list.set(i,new ArrayList<Integer>(list.get(j)));
                            list.get(i).add(a[i]);
                            if(max < leng[i]) {
                                max  = leng[i];
                                p = i;
                            }
                        }
                    }
                }
                if(j < 0 && leng[i] == 0) {
                    list.get(i).add(a[i]);
                    leng[i] = 1;
                }

            }
        }
        return list.get(p);
    }

第二种方法(借助path数组):

public List<Integer> largestDivisibleSubset(int[] a){
        List<Integer> list = new ArrayList<Integer>();
        if(a.length < 1) return list;
        Arrays.sort(a);
        int[] path = new int[a.length];
        int[] fun = new int[a.length];
        int i = 0, j = 0;
        int max = 0, p = 0;
        for(i = 0; i < a.length; i++){
            for(j = i - 1; j >= 0; j--){
                if(a[i] % a[j] == 0){
                    if(fun[i] < fun[j] + 1){
                        fun[i] = fun[j] + 1;
                        path[i] = j;
                    }
                    if(max < fun[i]){
                        max = fun[i];
                        p = i;
                    }
                }
            }
            if(j < 0 && fun[i] == 0){
                fun[i] = 1;
                if(max < 1) {
                    max = 1;
                }
            }
        }
        while(max>0){
            list.add(0, a[p]);
            p = path[p];
            max--;
        }

        return list;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值