📜  门| GATE CS 2018 |第 60 题(1)

📅  最后修改于: 2023-12-03 15:12:36.482000             🧑  作者: Mango

题目描述

给定一个长度为n的整数序列,从中找出一个长度最长严格递增子序列(subsequence)。例如, 序列 {0, 8, 4, 12, 2, 10, 6, 14, 1, 9} 的最长递增子序列为 {0, 4, 6, 9, 14}。

解题思路

在计算机科学中,最长递增子序列(Longest Increasing Subsequence,LIS)问题是指:给定一个无序的整数数组,求出其中最长上升子序列的长度。例如,给定 [10, 9, 2, 5, 3, 7, 101, 18],最长上升子序列是 [2, 3, 7, 101],长度为 4。注意,子序列不一定要连续。

一种求解LIS问题的思路是使用动态规划。我们用一个数组dp来记录长度为i的子序列的最后一项的最小值(注意,这里指的是最后一项的值,而不是下标)。比如,dp[2]记录长度为2的子序列的最后一项最小为什么数,dp[5]记录长度为5的子序列的最后一项最小为什么数。

从数组的第一个元素开始,我们逐个考虑每一个元素。对于第i个元素,我们考虑它能接在哪些长度的子序列的末尾。我们尝试更新每一个状态i,也就是我们找到了长度为i+1的子序列。遍历所有长度小于i+1的状态,如果它们的末尾元素小于当前元素,则说明当前元素可以接在它们的末尾形成更长的子序列。因此,我们需要用dp[]数组记录当前状态下的最优解。这个过程可以使用一个循环来实现。

代码如下:

def lengthOfLIS(nums):
    if not nums:
        return 0
    
    n = len(nums)
    dp = [1] * n
    
    for i in range(1, n):
        for j in range(i):
            if nums[i] > nums[j]:
                dp[i] = max(dp[i], dp[j] + 1)
    
    return max(dp)

复杂度分析

该算法使用了嵌套循环,时间复杂度为 O(n^2)。空间复杂度为 O(n)。有一个时间复杂度更优的算法,时间复杂度为 O(nlogn),这里不再赘述。

参考链接

门| GATE CS 2018 |第 60 题