算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !
今天和大家聊的问题叫做 最大整除子集,我们先来看题面:
https://leetcode-cn.com/problems/largest-divisible-subset/
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, or
answer[j] % answer[i] == 0
If there are multiple solutions, return any of them.
给你一个由 无重复 正整数组成的集合 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]
动态规划的思路,要求出最大整除的子集,首先拆分问题,从一个最小的子集再扩大为最大的子集,假设有一个最小整除子集[a,b](a
例如 [2,4,7,8,9,12,16,18] 在该题的dp数组为[1, 2, 1, 3,1, 3, 4, 2]
class Solution {
public List largestDivisibleSubset(int[] nums) {
int len = nums.length;
Arrays.sort(nums);
// 第 1 步:动态规划找出最大子集的个数、最大子集中的最大整数
int[] dp = new int[len];
Arrays.fill(dp, 1);
int maxSize = 1;
int maxVal = dp[0];
for (int i = 1; i < len; i++) {
for (int j = 0; j < i; j++) {
// 题目中说「没有重复元素」很重要
if (nums[i] % nums[j] == 0) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
if (dp[i] > maxSize) {
maxSize = dp[i];
maxVal = nums[i];
}
}
// 第 2 步:倒推获得最大子集
List res = new ArrayList();
if (maxSize == 1) {
res.add(nums[0]);
return res;
}
for (int i = len - 1; i >= 0 && maxSize > 0; i--) {
if (dp[i] == maxSize && maxVal % nums[i] == 0) {
res.add(nums[i]);
maxVal = nums[i];
maxSize--;
}
}
return res;
}
}
好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力 。
上期推文:
LeetCode1-360题汇总,希望对你有点帮助!
LeetCode刷题实战361:轰炸敌人
LeetCode刷题实战362:敲击计数器
LeetCode刷题实战363:矩形区域不超过 K 的最大数值和
LeetCode刷题实战364:加权嵌套序列和 II
LeetCode刷题实战365:水壶问题
LeetCode刷题实战366:寻找二叉树的叶子节点
LeetCode刷题实战367:有效的完全平方数