368. 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.

Example 1:

nums: [1,2,3]

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

Example 2:

nums: [1,2,4,8]

Result: [1,2,4,8]

int partition(int *nums, int low, int high) {
    int pivotkey = nums[low];
    while(low < high) {
        while(low < high && nums[high] >= pivotkey) --high;
        nums[low] = nums[high];
        while(low < high && nums[low] <= pivotkey) ++ low;
        nums[high] = nums[low];
    }
    nums[low] = pivotkey;
    return low;
}
void quickSort(int *nums, int from, int to) {
    if (from < to) {
        int pivot = partition(nums, from, to);
        quickSort(nums, from, pivot - 1);
        quickSort(nums, pivot + 1, to);       
    }
}

/**
 * Return an array of size *returnSize.
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* largestDivisibleSubset(int* nums, int numsSize, int* returnSize) {
    if (numsSize == 0) {
        *returnSize = 0;
        return NULL;
    }
    // 先排序
    quickSort(nums, 0, numsSize - 1);
    
    // 用于记录最长串的长度
    int counts[numsSize];
    counts[0] = 1;
    // 用来记住position处的上一个最长约束的position
    int last_max_inds[numsSize];
    // -1 代表上面没有
    last_max_inds[0] = -1;
    
    // 用于记录全局的最大长度和其inds
    int max = 1;
    int inds = 0;
    
    // 用于记录单个数的最长和它的上一个数的inds
    int tmp_max, tmp_inds;
    
    int i, j;
    for (i = 1; i < numsSize; ++i) {
        // 前面的数都不是其nums[i]的约数
        tmp_max = 1;
        tmp_inds = -1;
        
        for(j = 0; j < i; ++ j) {
            if (nums[i] % nums[j] == 0) {
                if (counts[j] + 1 > tmp_max) {
                    tmp_max = counts[j] + 1;
                    tmp_inds = j;
                }
            }
        }
        
        counts[i] = tmp_max;
        last_max_inds[i] = tmp_inds;
        
        // 更新全局的
        if (max < tmp_max) {
            max = tmp_max;
            inds = i;
        }
    }
    
    *returnSize = max;
    int *res = (int *) malloc(sizeof(int) * max);
    i = 0;
    res[i] = nums[inds];
    int last_inds = last_max_inds[inds];
    while(last_inds != -1) {
        res[++i] = nums[last_inds];
        last_inds = last_max_inds[last_inds];
    }
    quickSort(res, 0, max - 1);
    return res;
}



学习笔记:

1.看清题目特点, 根据题目的特点想算法。

2. 本文特点:

1. 若a % b == 0 && c % a == 0; 那么c % b == 0;

2. 所以当我们 已求得已a为最大数字的最长串后,则 a对于c来说:a串中所有的数都是c的约数

3. 从上面我们可以利用动态规划的思想,从小到大来求数的最长约数串。然后后面的数字可以使用比其小的数的结果。




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值