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
- }
- 如果,nums[i]%nums[j]==0
- 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 };