368. Largest Divisible Subset 最大可除子集

Given a set of distinct positive integers, find the largest subset such that every pair (S_i{}, S_j{}) of elements in this subset satisfies:

S_i{} % S_j{} = 0 or S_j{} % S_i{} = 0.

If there are multiple solutions, return any subset is fine.

Example 1:

Input: [1,2,3]
Output: [1,2] (of course, [1,3] will also be ok)

Example 2:

Input: [1,2,4,8]
Output: [1,2,4,8]

题意 :找出给出数组中最大可除子集,要求子集中的任意一对数 (S_i{}S_j{}) 都能满足S_i{} % S_j{} = 0 or S_j{} % S_i{} = 0.

思路:

1.由于输入的数组是无序的,所以要先将数组进行排序;

2.利用动态规划的思想,从头开始遍历整个数组,当遍历到某个数x时,将这个数除以它之前的每个数,当x能被前面的某个数y整除时,再判断此时y的可除子集的个数,若y是x前面所有数中子集最大的数,那x的可除子集个数=y的可除子集个数+1(x自身);

3.用一个数maxLength记录最大可除子集的长度;

maxIndex记录最大可除子集最后一位数的坐标;

用与输入数组等长的数组remainder[]记录每个数的最大可除子集大小 ,如下图

用与输入数组等长的数组pre[]记录每个数所在的最大可除子集中的前一个数。每当遍历完一个数x后,若x的可除子集是当前最大的,便用maxLength记录,并且当前数的坐标用maxIndex记录;并且将x所在可除子集的前一个数y的坐标 j 记录在pre数组中:pre[i]=j.(nums[i]:x,nums[j]:y)

nums
index0123456
nums2346789
remainder
index0123456
remainder0011021

 

pre
index0123456
pre-1-101-121

 

代码:

class Solution {
    public List<Integer> largestDivisibleSubset(int[] nums) {
        int len = nums.length;
        List<Integer> result = new ArrayList<Integer>();
        int[] Remainder = new int[len]; //记录可除子集数大小
        int[] pre = new int[len];  //可除子集中前一个数的坐标
        int maxLen = 0;   //最大可除子集的长度
        int maxIndex=0;   //最长可除子集最后一位数的坐标
        if(len==0) 
            return result;
        Arrays.sort(nums);
         for(int i=1;i<len;i++){
            for(int j=i-1;j>=0;j--){
                if(nums[i]%nums[j]==0 && Remainder[j]>=Remainder[i]){
                    //能整除且可除子集个数更大,则更新当前数可除子集的大小  
                    Remainder[i] = Remainder[j]+1;
                    //记录j为i所在可除子集的前一个数
                    pre[i]=j;
                }

            }
            if(Remainder[i]>maxLen){
                maxIndex = i;
                maxLen = Remainder[i];
            }
        }

        int index = maxIndex;
        while(maxLen-- >= 0){
            result.add(0,nums[index]); //List.add(0,value):将数插在数组的最前面
            index = pre[index];
        }
        return result;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值