LintCode刷题——Largest Divisible Subset

题目内容:

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.

Given nums = [1,2,4,8], return [1,2,4,8]

题目概述:

给定一个含不重复正整数元素的集合,返回该集合的任意一个子集,使其满足该子集中的元素两两之间存在一个数对另一个数取余为0;

算法分析:

可以先从数学上对该问题进行分析,看一个简单的例子:

对于集合[1,2,4],其满足该返回集合的条件,当该集合中加入满足与4取余为0的数时,该集合仍满足返回集合的条件。对于数 i<j<k,若 j%i=0, k%j=0, 则很容易推出 k%i=0。

因此对于本题,将给定的数组num[]从小到大进行排序。建立一个数组maxLength[]用来记录数组num[]中每一个位置所对应的其能连接的最大长度;建立一个lastIndex[]数组用来记录当前位置能连接的上一个数字的位置,然后进行以下算法:

  ①对数组进行初始化,将数组lastIndex[]中的每一个元素的值均置为-1,表示当前节点不存在可连接的上一个节点;

  ②对于每一个num[i],对其之前的所有元素进行遍历,找到能连接的最大长度,同时更新maxLength[i]与lastIndex[i];

  ③找到maxLength[]中的最大长度同时利用lastIndex[]进行结果的处理,最后return result;

代码:

  算法复杂度为O(n^2);

public List<Integer> largestDivisibleSubset(int[] nums) {
        // Write your code here
        Arrays.sort(nums);
        int length = nums.length;
        int maxIndex = -1;
        int max = 0;
        List<Integer> result = new ArrayList<>();
        if(length<2){
            return result;
        }
        int[] maxLength = new int[length];
        int[] lastIndex = new int[length];
        for(int i=0;i<length;i++){
            lastIndex[i] = -1;
        }
        for(int i=1;i<length;i++){
            //找到i元素的上一个可连接的最大长度的节点
            for(int j=0;j<i;j++){
                int temp = 0;
                if(nums[j]%nums[i]==0||nums[i]%nums[j]==0){
                    temp = maxLength[j] + 1;
                    if(temp>maxLength[i]){
                        maxLength[i] = temp;
                        lastIndex[i] = j;
                    }
                }
            }
            if(maxLength[i]>max){
                max = maxLength[i];
                maxIndex = i;
            }
        }
        //当数组nums中的每一个元素均不存在上一个可连的元素时则返回第一个元素节点链表;
        if(maxIndex==-1){
            result.add(nums[0]);
        }
        else{
            while(lastIndex[maxIndex]!=-1){
            result.add(nums[maxIndex]);
            maxIndex = lastIndex[maxIndex];
            }
            result.add(nums[maxIndex]);
        }
        return result;
    }

 

转载于:https://www.cnblogs.com/Revenent-Blog/p/7545347.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值