力扣 leetcode 300. 最长递增子序列(python)

Topic

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7]

Example_1

输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。

Example_2

输入:nums = [0,1,0,3,2,3]
输出:4

Example_3

输入:nums = [7,7,7,7,7,7,7]
输出:1

Tips

1 <= nums.length <= 2500
-104 <= nums[i] <= 104

Solution_1

利用最基本的动态规划方法进行解题

首先是推导转移方程:

从0到i进行遍历nums,那么dp[i] 的值代表 nums 前 i 个数字的最长子序列长度
设置j为[0, i)

当 nums[i] > nums[j]时
nums[i] 可以接在 nums[j] 之后
那么最长上升子序列长度为 dp[j] + 1

当 nums[i] <= nums[j]
nums[i]无法接在 nums[j] 之后
不满足最长上升子序列

同时在每次在j遍历nums得出以dp[i]为结尾的最长子序列的长度之后
与上一次遍历得到的值相比取最大

最终取dp中最大值即为所求

Code_1

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        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)
        print(dp)
        return max(dp)

Res_1

力扣 leetcode 300. 最长递增子序列(python)_第1张图片

Solution_2

借助动态规划及二分查找解决问题

设置数组dp用于存储与最长子序列等长的序列
对nums进行遍历
将每位元素二分插入 dp中:

如果 其比dp中最大的元素要大
则将其放入dp最后
否则,奖比它大的元素中最小的那个
用其替换掉

由此可将dp中保持满足最低条件的最长子序列

Code_2

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:      
        dp = [nums[0]]
        for i in range (len(nums)):
            if nums[i] > dp[-1]:
                dp.append(nums[i])
                continue
            
            left, right = 0, len(dp)-1
            while left < right:
                mid = left + (right - left) // 2
                if dp[mid] < nums[i]:
                    left = mid + 1
                else:
                    right = mid
            dp[left] = nums[i]
        return len(dp)


Res_2

力扣 leetcode 300. 最长递增子序列(python)_第2张图片

你可能感兴趣的:(leetcode,python,python,list,算法,动态规划,leetcode)