📜  门|门 IT 2005 |第 58 题(1)

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

门|门 IT 2005 |第 58 题
题目描述

有一个长度为n的数组a,请输出最长的 ‘长升序列’(注:长升序列是指符合条件的一个最长的子序列,序列中的元素可以不连续),并打印出所选元素的下标(第一个元素下标为0),如果有多个最长的长升序列,则输出最靠前的一个。

技术要求

本题需要使用动态规划算法实现。

解题思路

使用最长升序子序列算法来解决题目,由于长升序列可以不连续,因此需要使用动态规划算法来进行求解。

  • 定义状态

    • 定义状态h[i]为a[0]~a[i]中最长升序子序列的长度。
  • 定义转移方程

    • 对于状态h[i],搜索a[0]~a[i-1]中的所有比a[i]小的数,计算对应的状态h[j]+1,找到最大的状态值作为h[i]的值。

$$h[i]=max{h[j]+1}$$

  • 定义初始状态

    • 初始状态为h[0]=1,即序列前0个元素的最长升序子序列长度为1。
  • 定义边界条件

    • 对于i∈[1,n),计算h[0]~h[i-1]的最大值,以及该最大值对应的下标,即可得到最长升序子序列的长度和方案。
代码实现
def longest_increasing_subsequence(n: int, a: List[int]) -> List[int]:
    h = [1] * n
    p = [-1] * n
    for i in range(1, n):
        for j in range(i):
            if a[j] < a[i] and h[j] + 1 > h[i]:
                h[i] = h[j] + 1
                p[i] = j
    max_length, max_index = max([(h[i], i) for i in range(n)])
    res = []
    while max_index != -1:
        res.append(max_index)
        max_index = p[max_index]
    res.reverse()
    return res
总结

本题需要使用动态规划算法,采用最长升序子序列算法来解决问题。在实现时需要定义状态、转移方程、初始状态和边界条件,以得到最长升序子序列和方案。