📜  最长的递增子序列,该序列由先前选择的索引可除的索引元素组成(1)

📅  最后修改于: 2023-12-03 14:55:23.392000             🧑  作者: Mango

最长的递增子序列

给定一个整数数组,找到其中最长的严格递增子序列(LIS),使得该子序列中的每个元素的索引都是先前选择的索引的约数。

示例 1:

输入:[1,2,4,8] 输出:[1,2,4,8] 解释:最长的递增子序列是 [1,2,4,8] 。

示例 2:

输入:[1,3,6,7,9,4,10,5,6] 输出:[1,3,6,7,9,10] 解释:最长的递增子序列是 [1,3,6,7,9,10],其中每个元素的索引都是先前选择的索引的约数。

解决方法

这道题可以使用动态规划来解决,具体步骤如下:

设 dp[i] 表示以 nums[i] 结尾的最长递增子序列长度。

初始化 dp[i] 为 1。

状态转移方程为:

dp[i] = max(dp[i], dp[j] + 1) if nums[i] % nums[j] == 0 for j in range(i)

最终需要遍历 dp 数组,找到其中最大值 max_len 和对应索引 max_idx。

然后从 max_len 对应的索引 max_idx 开始,一直向前找到第一个满足 dp[i] + 1 == dp[max_idx] 并且 nums[max_idx] % nums[i] == 0 的索引 i。将该索引加入结果列表 res 中。

反转结果列表 res 并返回即可。

代码如下,时间复杂度为 O(n^2):

from typing import List

def largestDivisibleSubset(nums: List[int]) -> List[int]:
    n = len(nums)
    if n <= 1:
        return nums
    nums.sort()
    dp = [1] * n
    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)
    max_len = max(dp)
    max_idx = dp.index(max_len)
    res = []
    for i in range(max_idx, -1, -1):
        if dp[i] == max_len and (not res or res[-1] % nums[i] == 0):
            res.append(nums[i])
            max_len -= 1
    return res[::-1]
总结

这道题需要先对数组进行排序,然后使用动态规划来求解最长的递增子序列。在动态规划的同时需要记录下每个子序列的前一个元素是哪个,以便后面反向遍历时方便记录整个子序列。最终需要反转得到的结果列表才是正确的顺序。