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]
标签:动态规划
https://discuss.leetcode.com/topic/49456/c-solution-with-explanations
显然,首先要对nums排序,假设已经有了一个子集P = { 4, 8, 16 },现在我们要往里加一个满足要求的数,这个数要么被4整除,要么可以整除16,即这个数可以是2,也可以是32。
所以,我们可以用一个dp数组来存储最大子集的长度,用一个辅助数组parent来存储最大子集的索引。
dp[n] = the length of the largest divisible subset whose largest number is nums[n]
dp[n+1] = max{ ( 1 + dp[i] ) if nums[n+1] mod nums[i] == 0 ; else =0}
虽然上面dp[n]表示以nums[n]为最大值的子集长度,但是实现的时候,我们是反向的,即dp[n]表示以nums[n]为最小值的长度,这样可以不用对最后的结果进行翻转就能返回,详情见代码。
class Solution {
public:
vector<int> largestDivisibleSubset(vector<int>& nums) {
vector<int> result;
if(nums.empty()) return result;
sort(nums.begin(), nums.end());
vector<int> dp(nums.size(),0);
vector<int> parent(nums.size(),0);
int cnt = 0;
int index = 0;
for(int i = nums.size() -1; i >=0; i--){
for(int j = i; j < nums.size();j++){
if(nums[j] % nums[i] == 0 && dp[i] < dp[j] + 1){
// if nums[j] mod nums[i] == 0, it means dp[j] can form a larger subset by putting nums[i] into dp[j]
dp[i] = dp[j] +1;
parent[i] = j; //记录前一个数的索引位置
if(dp[i] > cnt){
cnt = dp[i];
index = i;
}
}
}
}
for(int k = 0; k < cnt; k++){
result.push_back(nums[index]);
index = parent[index];
}
return result;
}
};