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]
给定一个数组,其元素均为正整数,找出元素最多的这样一个子数组:该数组任意两个元素(设为Si,Sj),满足Si%Sj==0或Sj%Si==0。若存在多种满足条件的子数组,返回其中任意一个均可。
分析:
设原数组有n个元素(s1,s2,…,sn),并记为Sn,设其满足条件的最大子集为Rn。取Sn前n-1个元素构成的子集Sn-1,设其满足条件的最大子集为Rn-1。不难得出,若sn与Rn-1中任一元素ri满足sn%ri==0或ri%sn==0,则Rn=(Rn-1,sn);否则Rn=Rn-1,记Rn={Rn-1,sn}。而Rn-1={Rn-2,sn-1},不停迭代,可知Rn={{{{R1,s0},s1},…},sn}。这是典型的动态规划问题,可用动态规划来求解。为简便起见,先将输入数组S按元素从小到大的顺序排序。遍历数组S,用数组dp来记录每取一个元素时满足条件的最大子集的长度,如dp[i]表示数组S前i个元素构成的子数组的满足条件的最大子数组的长度;另用一个数组prev来记录最大子数组的当前元素的前一个元素的索引,以便后续查找出最大子数组。遍历完成后,遍历数组dp,找出最大子数组的长度maxlen,并记录其最后一个元素的索引idx。最后,根据索引数组prev,从原数组S中取出最大子数组即可。
代码如下:
vector<int> largestDivisibleSubset(vector<int>& nums)
{
vector<int> rst;
if (nums.empty())
return rst;
int cnt = nums.size();
vector<int> dp(cnt, 0);
vector<int> prev(cnt, 0);
int maxlen = 0, idx = 0;
sort(nums.begin(), nums.end());
for (int i = 1; i < cnt; i++)
{
for (int j = i - 1; j >= 0; j--)
{
if (nums[i] % nums[j] == 0 && dp[i] < dp[j] + 1)
{
dp[i] = dp[j] + 1;
prev[i] = j;
}
}
}
for (int i = 0; i < cnt; i++)
{
if (maxlen < dp[i])
{
maxlen = dp[i];
idx = i;
}
}
for (int i = idx; i >= 0, maxlen >= 0;)
{
rst.push_back(nums[i]);
i = prev[i];
maxlen--;
}
sort(rst.begin(), rst.end());
return rst;
}
浙公网安备 33010602011771号