368. Largest Divisible Subset

问题:

给定一组数,求其中最大子set,使得set中其中任意两元素之间:

a%b=0 or b%a=0

Example 1:
Input: nums = [1,2,3]
Output: [1,2]
Explanation: [1,3] is also accepted.

Example 2:
Input: nums = [1,2,4,8]
Output: [1,2,4,8]
 

Constraints:
1 <= nums.length <= 1000
1 <= nums[i] <= 2 * 10^9
All the integers in nums are unique.

  

解法:DP

  • 状态:dp[i]
    • i:第0~i个元素中,包含nums[i],能构成最大的满足题意的子set的元素个数。
  • 选择:MAX {(j:0~i)
    • 如果,nums[i]%nums[j]==0
      • dp[j]+1
    • 否则,skip
    • }
  • base:
    • dp[i]=1

⚠️ 注意:我们将nums排序后,有一个规律。k<j<i

后面的数nums[i],如果能够被前面的某个数nums[j]整除  ->nums[i]%nums[j]==0

那么在nums[j]上,j之前所有能整除nums[j]的数nums[k]  ->nums[j]%nums[k]==0

都能整除nums[i]->nums[i]%k==0  ->nums[i]%nums[k]==0

所求子set的元素最大个数,则是,dp[i]中求最大值。max_idx=i(dp[i]最大)

而,题意要求这个set具体是什么。

我们需要同时记录 i 前面的 j,依次推导出整个set元素。

pre_idx[i]=j

pre_idx[j]=k ......

代码参考:

 1 class Solution {
 2 public:
 3     //dp[i]:include nums[i]: the set which every pair can %=0
 4     //
 5     vector<int> largestDivisibleSubset(vector<int>& nums) {
 6         int n = nums.size();
 7         vector<int> res;
 8         sort(nums.begin(), nums.end());
 9         vector<int> dp(n,1);
10         vector<int> pre_idx(n,-1);
11         int max_idx = 0;
12         for(int i=1; i<n; i++) {
13             for(int j=0; j<i; j++) {
14                 if(nums[i]%nums[j]==0 && dp[i]<dp[j]+1) {
15                     dp[i] = dp[j]+1;
16                     pre_idx[i] = j;
17                 }
18             }
19             if(dp[i]>dp[max_idx]) {
20                 max_idx=i;
21             }
22         }
23         for(int i=max_idx; i>=0; i=pre_idx[i]) {
24             res.push_back(nums[i]);
25         }
26         return res;
27     }
28 };
原文地址:https://www.cnblogs.com/habibah-chang/p/14664178.html