Leetcode之 largest divisible set

题目

题目地址 :https://leetcode.com/problems/largest-divisible-subset/

题意解析

给定一个数组,这个数组数唯一且为正数,求在这个数组中,满足能整除的最大集合。

求解

很自然地想到用动态规划,因为满足重叠子问题和最优子结构
重叠子问题:整个数组的最大集合,可以认为是多个子问题组成的
最优子结构:反证法,显而易见。


定义最优解:最大集合是什么。

定义最优解的值:最大集合有多少个数。

定义 f[i]表示从0到i最大能整除集合里的个数。

递归式求解最优解的值:

f[i]= max{f[i],f[j]+1}    if nums[i]%nums[j]==0

其中 j从i-1 downto 0

初始化条件:对于每个f[i],至少有i%i ==0;定义为1;

根据题意需要记录集合的内容,故需要记录每一步执行的index


Code

ac代码

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Created by loveqh on 2016/8/13.
 */
public class LargestDivisibleSet {
    public List<Integer> largestDivisibleSubset(int[] nums) {
        List<Integer> result = new ArrayList<Integer>();
        Arrays.sort(nums);
        int[] f = new int[nums.length];
        int[] pre = new int[nums.length];
        int max = -1;
        int index = -1;
        //初始化f 和前导
        for (int i = 0; i < f.length; i++) {
            f[i] = 1;
            pre[i] = -1;
        }
        if (nums.length == 1) {
            result.add(nums[0]);
            return result;
        }
        for (int i = 1; i < nums.length; i++) {
            //一轮循环,找到从0到i的可整除集合的长度
            for (int j = i - 1; j >= 0; j--) {
                if (nums[i] % nums[j] == 0 && (f[i] < f[j] + 1)) {
                    f[i] = f[j] + 1;
                    //记录i的前导
                    pre[i] = j;
                }
            }
            //relax max的值
            if (max < f[i]) {
                max = f[i];
                index = i;
            }
        }
        if (index != -1) {
            result.add(nums[index]);
        }
        while (index > 0) {
            if (pre[index]!=-1){
                result.add(nums[pre[index]]);
                index = pre[index];
            }else {
                break;
            }
        }
        //求得的result为逆序的,应该转化为开始的样子
        Collections.reverse(result);
        return result;
    }

    public static void main(String[] args) {
        int[] a = {546,669};
        List<Integer> res = new LargestDivisibleSet().largestDivisibleSubset(a);
        for (Integer value : res) {
            System.out.print(value + "   ");
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值