[动态规划]-- 300 -最长上升子序列 - Python

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

示例:

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

说明:

  • 可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
  • 算法的时间复杂度应该为 O ( n 2 ) O(n^2) O(n2)

进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?


要找无序数组中的最长上升子序列,相当于找所有的上升子序列中最长的那个。因此,如果我们能找到所有可能的上升子序列,那么长度最长的那个不就是想要的结果吗?因此,最直接的方法就是暴力法,依次判断从当前数出发,后续列表中的数据能否构成上升序列:

  • 如果当元素比已有上升序列的最后一个元素大,那么将其加到序列尾部,继续往后判断
  • 否则,保存当前的上升序列,然后将当前元素作为新的上升序列的第一个元素,继续往后判断
class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        if not nums: return 0
        if len(nums) == 1: return 1

        r = [[-99999]]
        for i in range(len(nums)):
            for j in range(len(r)):
                if nums[i] > r[j][-1]:
                    t = r[j].copy()
                    t.append(nums[i])
                    r.append(t)
                else:
                    r.append([nums[i]])

        print (r)
        maxL = 1 
        for i in r:
            if len(i) >= maxL:
                maxL = len(i)

        return maxL - 1

但是它不能通过所有的测试用例,当数组的长度很长时,算法的执行会超出时间限制。


[动态规划]-- 300 -最长上升子序列 - Python_第1张图片

这说明在求解的过程中,我们多了很多无谓的计算,如果能利用到已经得到的结果来求最终的结果,那么用时不就下去了吗。题目要求返回的是最长上升序列的长度,而不是具体的序列。因此,在计算的过程中只需要记录可能的序列的长度即可。

我们建立一个数组来记录到当前元素为止,可能的上升序列的长度。由于每一个元素单独可看做是上升序列,因此,数组元素的初始值都是1。假设访问到第i个元素nums[i]时,前面的子序列对应的dp数组的记录4更新,那么判断nums[i]能否构成上升序列时,只需要判断数组中 0 ∼ i 0 \sim i 0i的元素和nums[i]的大小即可:

  • 如果 0 ∼ i 0 \sim i 0i中的元素都大于nums[i],那么它们和nums[i]就无法构成上升序列,那么dp[i]的值就不发生改变
  • 如果nums[i]大于其中的某一个元素,那么加上nums[i]依然可以构成上升序列,那么dp[i]的值就可能发生改变,具体的规则是 d p [ i ] = max ⁡ ( d p [ i ] , d p [ j ] + 1 ) dp[i] = \max(dp[i], dp[j] + 1) dp[i]=max(dp[i],dp[j]+1)

    [动态规划]-- 300 -最长上升子序列 - Python_第2张图片

经过分析,我们便得到了上述的动态转移方程,最后只需按照动态规划的方法求解即可。解题代码如下:

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        if not nums: return 0
        
        dp = [1] * len(nums)
        for i in range(len(nums)):
            for j in range(i):
                if nums[j] < nums[i]:
                    dp[i] = max(dp[i], dp[j] + 1)
                    
        return max(dp)

你可能感兴趣的:(Leetcode)