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