动态规划-最长可互除子序列 Largest Divisible Subset

Posted timhy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划-最长可互除子序列 Largest Divisible Subset相关的知识,希望对你有一定的参考价值。

2018-08-28 17:51:04

问题描述:

技术分享图片

问题求解:

本题是一个求最优解的问题,很自然的会想到动态规划来进行解决。但是刚开始还是陷入了僵局,直到看到了hint:LIS,才有了进一步的思路。下面是最初的一个解法。使用的是map来记录信息。

    public List<Integer> largestDivisibleSubset(int[] nums) {
        if (nums.length == 0) return new ArrayList<>();
        Arrays.sort(nums);
        Map<Integer, List<Integer>> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            List<Integer> tmp = null;
            int maxlen = 0;
            for (int j = 0; j < i; j++) {
                if (nums[i] % nums[j] == 0 && maxlen < map.get(nums[j]).size()) {
                    tmp = new ArrayList<>(map.get(nums[j]));
                    maxlen = tmp.size();
                }
            }
            if (tmp == null) tmp = new ArrayList<>();
            tmp.add(nums[i]);
            map.put(nums[i], tmp);
        }
        int maxlen = 0;
        List<Integer> res = null;
        for (Integer i : map.keySet()) {
            if (map.get(i).size() > maxlen) {
                res = map.get(i);
                maxlen = res.size();
            }
        }
        return res;
    }

当然上述的代码效率不是很高,我们可以使用两个数组来进行维护。

    public List<Integer> largestDivisibleSubset(int[] nums) {
        List<Integer> res = new ArrayList<>();
        if (nums.length == 0) return res;
        Arrays.sort(nums);
        int[] dp = new int[nums.length];
        int[] prev = new int[nums.length];
        int max = 0;
        int index = -1;
        for (int i = 0; i < nums.length; i++) {
            prev[i] = -1;
            dp[i] = 1;
            for (int j = 0; j < i; j++) {
                if (nums[i] % nums[j] == 0 && dp[j] + 1 > dp[i]) {
                    dp[i] = dp[j] + 1;
                    prev[i] = j;
                }
            }
            if (dp[i] > max) {
                max = dp[i];
                index = i;
            }
        }
        while (index != -1) {
            res.add(nums[index]);
            index = prev[index];
        }
        return res;
    }

 

以上是关于动态规划-最长可互除子序列 Largest Divisible Subset的主要内容,如果未能解决你的问题,请参考以下文章

动态规划 最长公共子序列 过程图解

用数学语言说一下动态规划求数列最长递增子序列的解

算法 LC 动态规划 - 最大递增子序列

最长公共子序列(LCS)动态规划解题笔记

最长公共子序列(LCS)动态规划解题笔记

动态规划之最大递增子序列