LeetCode每日抑题之——最大整除子集

原题链接

题目描述

给你一个由 无重复 正整数组成的集合 nums ,请你找出并返回其中最大的整除子集 answer ,子集中每一元素对 (answer[i], answer[j]) 都应当满足:
answer[i] % answer[j] == 0 ,或
answer[j] % answer[i] == 0
如果存在多个有效解子集,返回其中任何一个均可。

示例 1:

输入:nums = [1,2,3]
输出:[1,2]
解释:[1,3] 也会被视为正确答案。
示例 2:

输入:nums = [1,2,4,8]
输出:[1,2,4,8]

提示:

1 <= nums.length <= 1000
1 <= nums[i] <= 2 * 109
nums 中的所有整数 互不相同

题目分析:
这一题我们可以使用动态规划来完成,那么关键是找出我们应该表示什么状态和状态的转移方程。在这一题中我们要求的是最大的整除子集,那么很容易想到用数组dp,其中dp[i]表示包括nums[i]在内的,nums[0],nums[1],nums[2],…nums[i]内最大的整除子集。注意,这里nums[i]必须被选择。

那么dp[[0-N]都应该被初始化值为1。

接下来考虑状态的转移:
枚举nums[0],nums[1],…nums[i-1]内所有元素,如果nums[i]能够整除它们,就该让dp[i]=Math.max(dp[i],dp[j]+1),注意这里不能简单的让dp[i]++。我们可以简单举一个例子说明这个道理:
[4,8,10,240]这个数组,如果我们每枚举一次能够整除让dp[i]++,那么dp[3]就应该等于4。实际上10不能够整除4和8,因此是错误的。因为这样不能够保证子集内部都能被整除。

我们这样做仅仅只是找到了最大的整除子集长度,那么怎么找到对应的元素集合呢?试想,假设MAX(dp[i])==4,那么我们只需要顺势找到dp[i]==3,dp[i]==2,dp[i]==1的几种情况,如果dp[i]==4时最大的元素maxVal能够整除dp[i]==3时对应位置的元素,那么就加入该元素到集合中。同时MaxVal应该对应dp[i]==3时对应的元素,因为dp[i]==3的位置可能有多个,我们必须保证我们找到的是正确的。


具体程序:

class Solution {
    public List<Integer> largestDivisibleSubset(int[] nums) {
        List<Integer> lists=new ArrayList<>();
        int n=nums.length,i,j;
        int []dp=new int[n];
        Arrays.fill(dp,1);
        Arrays.sort(nums);
        int maxSize=1,maxVal=nums[0];
        for(i=1;i<n;i++){
            for(j=0;j<i;j++){
                if(nums[i]%nums[j]==0) dp[i]=Math.max(dp[i],dp[j]+1);//状态转移方程很重要
            }
            maxSize=Math.max(maxSize,dp[i]);
            if(maxSize==dp[i]) maxVal=nums[i];
        }
        for(i=n-1;i>=0&& maxSize>0;i--){
            if(maxSize==dp[i] && maxVal%nums[i]==0){
                maxSize--;
                lists.add(nums[i]);
                **maxVal=nums[i];//必须让maxVal=nums[i];**
            }
        }
        return lists;
    }
}
``
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值