leetcode368.最大整除子集

题目大意

给出一个由无重复的正整数组成的集合,找出其中最大的整除子集,子集中任意一对 (Si,Sj) 都要满足:Si % Sj = 0 或 Sj % Si = 0。

如果有多个目标子集,返回其中任何一个均可。

示例 1:

输入: [1,2,3]
输出: [1,2] (当然, [1,3] 也正确)

示例 2:

输入: [1,2,4,8]
输出: [1,2,4,8]

解题思路

题目中说可以是Si % Sj = 0 或 Sj % Si = 0,为了方便起见,我们首先对数组排序,总是用大数去除以小数。
接下来是动态规划的思想。当遍历到位置i时,遍历0~i-1位置的元素,如果能够被nums[i]整除,则dp[i]=max(dp[i], dp[j]+1),即dp[i]表示的是:数组中最大值是nums[i]时,能够组成的最长序列的长度。同时每次把最大长度和最大值的索引记录下来。

当遍历完数组后(O(N2)),从最大索引位置向前遍历,如果该位置的值能够被记录的最大值整除,则加入最后结果中(需要注意的是,6%2=0, 6%3=0,但是2和3并不满足关系,因此要满足dp[i]要满足和最大长度的关系)。

class Solution {
public:
    vector<int> largestDivisibleSubset(vector<int>& nums) {
    	if (nums.empty())
    		return {};
    	if (nums.size() == 1)
    		return {nums[0]};

    	sort(nums.begin(), nums.end());

    	int maxIndex = 0, maxCount = 1;
    	int length = nums.size();

    	vector<int> dp(length, 1);

    	for (int i = 1; i < length; ++i){
    		for (int j = 0; j < i; ++j){
    			if (nums[i] % nums[j] == 0)
    				dp[i] = max(dp[i], dp[j] + 1);
    		}
    		if (dp[i] > maxCount){
    			maxCount = dp[i];
    			maxIndex = i;
    		}
    	}

    	vector<int> res;
    	int firstNum = nums[maxIndex];
    	for (int i = maxIndex; i >= 0; --i){
    		if (firstNum % nums[i] == 0 && dp[i] == maxCount){
    			res.push_back(nums[i]);
    			// 防止出现6%2=0和6,但2和3不满足关系的情况
    			--maxCount;
    		}
    	}
    	return res;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_41092190/article/details/106186850