368. 最大整除子集
368. 最大整除子集
🟠 🔖 数组 数学 动态规划 排序 🔗 力扣 LeetCode
题目
Given a set of distinct positive integers nums, return the largest subset answer such that every pair (answer[i], answer[j]) of elements in this subset satisfies:
answer[i] % answer[j] == 0, oranswer[j] % answer[i] == 0
If there are multiple solutions, return any of them.
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 <= 10001 <= nums[i] <= 2 * 10^9- All the integers in
numsare unique.
题目大意
给你一个由 无重复 正整数组成的集合 nums ,请你找出并返回其中最大的整除子集 answer ,子集中每一元素对 (answer[i], answer[j]) 都应当满足:
answer[i] % answer[j] == 0,或answer[j] % answer[i] == 0
如果存在多个有效解子集,返回其中任何一个均可。
示例 1:
输入: nums = [1,2,3]
输出:[1,2]
解释:[1,3] 也会被视为正确答案。
示例 2:
输入: nums = [1,2,4,8]
输出:[1,2,4,8]
提示:
1 <= nums.length <= 10001 <= nums[i] <= 2 * 10^9nums中的所有整数 互不相同
解题思路
排序数组
- 对
nums进行升序排序,以确保在后续遍历中可以利用整除性质。
- 对
动态规划求解
- 定义
dp[i]表示以nums[i]结尾的最大整除子集的长度。 - 通过额外的
parent[i]数组记录前驱节点索引,从而避免回溯时重复判断整除条件。 - 使用双层循环,遍历
nums中的每一对元素:- 对于每个
nums[i],遍历nums[0]到nums[i - 1],如果满足nums[i] % nums[j] === 0: - 则更新
dp[i] = max(dp[i], dp[j] + 1),表示通过nums[j]扩展出更长的子集。 - 记录路径
parent[i] = j,以便回溯生成结果。
- 对于每个
- 定义
回溯构建结果
- 根据
dp数组找到最大整除子集的终点索引maxIdx。 - 通过回溯
parent数组直接生成结果子集。 - 从
parent[maxIdx]依次回溯,将符合条件的元素加入结果子集。
- 根据
返回结果
- 最后返回子集
res。
- 最后返回子集
复杂度分析
- 时间复杂度:
O(n^2),外层遍历每个元素,内层检查所有前驱节点,形成二重循环。 - 空间复杂度:
O(n),需要额外的dp和parent数组。
代码
/**
* @param {number[]} nums
* @return {number[]}
*/
var largestDivisibleSubset = function (nums) {
nums.sort((a, b) => a - b);
const n = nums.length;
const dp = new Array(n).fill(1);
const parent = new Array(n).fill(-1); // 记录前驱索引
let maxSize = 1,
maxIdx = 0;
for (let i = 1; i < n; i++) {
for (let j = 0; j < i; j++) {
if (nums[i] % nums[j] == 0 && dp[i] < dp[j] + 1) {
dp[i] = dp[j] + 1;
parent[i] = j;
}
}
if (dp[i] > maxSize) {
maxSize = dp[i];
maxIdx = i;
}
}
let res = [];
// 直接通过 parent 数组回溯
for (let i = maxIdx; i >= 0; i = parent[i]) {
res.push(nums[i]);
if (parent[i] == -1) break;
}
return res;
};
