Thursday, July 7, 2016

[Algorithm] Largest Divisible Subset

Largest Divisible Subset


Problem Statment

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]


Solution: Dynamic Programming & Sorting

Let's first look at the following equations:

Given that nums[i] > nums[j] > nums[k], if:

nums[i] % nums[j] == 0 and nums[j] % nums[k] == 0, then

nums[i] % nums[k] == 0 must also be true.

So let the state dp[j] of nums[j] be the count of divisible numbers less or equal to nums[j], and given nums[j] > nums[i] and nums[j] % nums[i] == 0, we can have dp[i] = dp[j] + 1. And we can keep track of the longest length of divisible subset.

The problem wants us to find out the full sequence, so when never we update dp[i] we shall keep track of the index j which leads to this index i. And when we are worst-casing the length, we need to keep track of the ending index i.

To get the full sequence, we simply backtrace from ending index back to the beginning of this sequence.

Code implementation:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Solution {
public:
    vector<int> largestDivisibleSubset(vector<int>& nums) {
        if (nums.size() < 2) return nums;
        
        sort(nums.begin(), nums.end());
        int n = nums.size();
        vector<int> dp(n, 1);
        vector<int> backtrace(n, -1);
        int endIdx = 0;
        
        for (int i=0; i<n; i++) {
            for (int j=0; j<i; j++) {
                if (nums[i] % nums[j] != 0) continue;
                
                if (dp[i] < dp[j] + 1) {
                    dp[i] = dp[j] + 1;
                    backtrace[i] = j;
                    if (dp[i] > dp[endIdx]) {
                        endIdx = i;
                    }
                }
            }
        }
        
        vector<int> result;
        while (endIdx != -1) {
            result.push_back(nums[endIdx]);
            endIdx = backtrace[endIdx];
        }
        
        return result;
    }
};

No comments:

Post a Comment