LeetCode刷题|368最大整除子集(动态规划)

今天的每日一题还是一个动态规划题目。

题目描述

在这里插入图片描述
题目地址:最大整除子集

动态规划

如果考虑暴力法的话这道题应该怎么做呢,最简单的能想到的方法就是枚举每一个元素作为开头,然后遍历其他元素。但是这种方法并不可靠,可以举个例子看一下:
[ 9 , 18 , 54 , 90 , 108 , 180 , 360 , 540 , 720 ] [9,18,54,90,108,180,360,540,720] [9,18,54,90,108,180,360,540,720]这样一个数组,从9开始的话会得到 [ 9 , 18 , 54 , 108 , 540 ] [9,18,54,108,540] [9,18,54,108,540],但是实际上还有更长的结果 [ 9 , 18 , 90 , 180 , 360 , 720 ] [9,18,90,180,360,720] [9,18,90,180,360,720],而题目要求我们返回最长的结果,这种方法显然是不行的。
下面来开始考虑如何使用动态规划解决这个问题。这个问题是一个序列DP问题,每一个状态都依赖于与前一个状态的关系,也就是说,当前元素nums[i]能否接在nums[j]后面,取决于nums[i] % nums[j]结果是否为0。了解了这一点,那么我们定义数组dp[],dp[i]表示当前元素是所在序列的第几个位置。还是举个例子:

nums24789121620
dp12131343

定义了dp之后,要怎么求得dp[i]呢。首先我们得把数组按从小到大排个序,因为要使得nums[i] % nums[j]等于0,nums[i]就一定要比nums[j]大才行。然后依次与i前面的数进行%运算,如果运算结果为0,那么dp[i]就等于dp[j]+1,也就是在位置j的元素后面一位。但是由于前面不止一个元素,所以需要更新dp[i],选出最大的dp[i]。
得到dp数组结果,也就是上面表格的结果之后,我们根据表格内容倒着遍历一遍把最长的一个串取出来就可以了。

class Solution:
    def largestDivisibleSubset(self, nums: List[int]) -> List[int]:
        n = len(nums)
        nums.sort()
        dp = [1] * n
        maxSize = 1
        maxVal = dp[0]
        for i in range(1,n):
            for j in range(i):
                if nums[i] % nums[j] == 0:
                    dp[i] = max(dp[i], dp[j]+1) 
            if dp[i] > maxSize:
                maxSize = dp[i]
                maxVal = nums[i]
        
        res = []
        if maxSize==1:return [nums[0]]
        k = n-1
        while k >= 0:
            if dp[k] == maxSize and maxVal % nums[k] == 0:
                res.append(nums[k])
                maxVal = nums[k]
                maxSize = maxSize-1
            k = k-1
        return res

maxSize的作用是记录下最长序列的长度,在最后得到结果数组时每加入一个元素maxSize就减一。maxVal记录的是最大序列的最大的值,因为最后得到结果的时候可能会出现dp数组多个位置都是同一个数,这时候就需要用maxVal进行%运算,结果为0才是这一结果序列的元素。
最后,因为是倒着遍历,所以最后返回的结果是倒序的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值