leetcode 300. 最长上升子序列

给定一个无序的整数数组,找到其中最长上升子序列的长度。


示例:

输入: [10,9,2,5,3,7,101,18]
输出: 4 
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
说明:

可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n2) 。
进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?


动态规划

class Solution(object):
    def lengthOfLIS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0
        dp = [1 for _ in range(len(nums))]
        for i in range(1,len(nums)):
            num = nums[i]
            maxLength = 1
            for j in range(i-1,-1,-1):
                if num > nums[j]:
                    maxLength = max(maxLength, dp[j]+1)
            dp[i] = maxLength
        return max(dp)

这道题比较容易联想到用动态规划来做。我们用dp[i]来表示以第i个数字为结尾的最长升序子序列长度。假设有数组[2, 3, 7, 5]这四个数,对于dp[0]也就是以2为结尾的最长升序子序列为2,长度为1。dp[1] = 2,序列为[2,3],dp[2] = dp[3] = 3,序列分别为[2,3,7]以及[2,3,5]。观察其规律我们可以总结出状态转移方程,dp[i]只跟前面比它还要小的数有关,比如对于数字5,它的dp只和2,3的dp有关,7比5大并不会影响其构成子序列。所以只比较3,dp[3] = dp[1] +1,只比较2的话dp[3] = dp[0] + 1,最后dp[3]取其中最大的值。所以我们需要双层for循环,第一层遍历每一个元素,然后第二层取遍历i元素前面的每一个元素,然后取得当次能取到的最大值。初始条件,dp[0]=1,即子序列就为它本身,长度为1。时间复杂度为O(n^2)。

你可能感兴趣的:(leetcode)