题目链接:leetcode.
三重循环,但思路根本就是错的,哎
42 / 48 个通过测试用例
[5,9,18,54,108,540,90,180,360,720]
输出 [9,18,54,108,540]
预期结果 [9,18,90,180,360,720]
class Solution {
public:
vector<int> largestDivisibleSubset(vector<int>& nums) {
int N = nums.size();
vector<vector<int>> ans;
int maxx = 0;
for(int i = 0;i < N;++i)
{
vector<int> tmp(1, nums[i]);
for(int j = i + 1;j < N;++j)
{
bool flag = true;
for(auto x : tmp)
{
if(nums[j] % x != 0 && x % nums[j] != 0)
{
flag = false;
break;
}
}
if(flag)
{
tmp.push_back(nums[j]);
}
}
if(maxx < tmp.size())
maxx = tmp.size();
ans.push_back(tmp);
}
for(int i = 0;i < N;++i)
{
if(ans[i].size() == maxx)
return ans[i];
}
return {};
}
};
原来是要用动态规划,如果之前做300. 最长递增子序列的时候我记住了该多好
如果一个数,是当前整除子集中最大数的倍数,则该数可以加入整除子集中构成一个更大的子集
利用这个思想,dp[i]
存放以nums[i]
为最大数的整除子集的长度,如果nums[j]
是nums[i]
的倍数,则dp[j] = dp[i] + 1
- 先对数组排序O(nlogn)
- 初始化
dp
数组,所有的dp[i]
都等于1,从前往后计算dp[i]
,每次计算都要遍历dp[0]
到dp[i-1]
,O(n^2) - 找出最大的整除子集的长度
max_len
O(n)
根据max_len
求取最大整除子集 O(n)
- 将对应
max_len
的数字num
加入ans
数组中,从num
开始往前遍历,找到dp
值为max_len - 1
且能整除num
的数,将其作为新的num
,加入ans
,max_len
减一,继续向前遍历,直到max_len == 0
/*
执行用时:40 ms, 在所有 C++ 提交中击败了98.25%的用户
内存消耗:8.5 MB, 在所有 C++ 提交中击败了63.07%的用户
*/
class Solution {
public:
vector<int> largestDivisibleSubset(vector<int>& nums) {
sort(nums.begin(), nums.end());
int N = nums.size();
vector<int> dp(N, 1);
int max_len = 1;
for(int i = 1;i < N;++i)
{
int maxx = 0;
for(int j = 0;j < i;++j)
{
if(nums[i] % nums[j] == 0)
{
maxx = max(maxx, dp[j]);
}
}
dp[i] += maxx;
max_len = max(max_len, dp[i]);
}
vector<int> ans;
for(int i = N - 1;i >= 0 && max_len;--i)
{
if(dp[i] == max_len)
{
if(ans.empty())
{
ans.push_back(nums[i]);
max_len--;
}
else if(ans.back() % nums[i] == 0)
{
ans.push_back(nums[i]);
max_len--;
}
}
}
return ans;
}
};