leetcode 368. 最大整除子集(dp)-golang版本 | Go主题月

331 阅读1分钟

给你一个由 无重复 正整数组成的集合 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 <= 1000 1 <= nums[i] <= 2 * 109 nums 中的所有整数 互不相同

解题思路

从小到大进行排序,每次判断两个元素的整除关系时,只需要枚举前面元素,判断是否存在整除关系即可。 因为整除关系存在传递性,例如1,2,4,8,16,16整除8以外,同时也能整除能被8整除的元素(例如 1,2,4) 因此只需要一个一维数组记录当前元素能够整除元素的个数 状态转移方程为:

		for j,v:=range nums[:i] {//遍历前面元素
			if nums[i]%v==0&&dp[j]+1>dp[i]{//当前nums[j]可以被nums[i]整除
				dp[i]=dp[j]+1//因此与nums[j]有整除关系的,与nums[i]也存在相同的整除关系 
                //加一是因为与nums[i]与nums[j]也存在整除关系
			}
		}

代码

func largestDivisibleSubset(nums []int) []int {

	sort.Ints(nums)
	n := len(nums)
	dp := make([]int, n)
	for i:=range dp{
		dp[i]=1
	}
	maxS,maxV:=1,nums[0]
	for i := 1; i < n; i++ {

		for j,v:=range nums[:i] {
			if nums[i]%v==0&&dp[j]+1>dp[i]{
				dp[i]=dp[j]+1
			}
		}
		if dp[i]>maxS{
			maxS,maxV=dp[i],nums[i]
		}
	}
	var res []int
    
	if maxS==1{
        res=append(res,maxV)
		return res
	}
	for i := n-1; i >=0 ; i-- {
		if maxS>0&&maxV%nums[i]==0&&dp[i]==maxS{
			maxS--
			maxV=nums[i]
			res=append(res,maxV)
		}
	}

	return res

}