LeetCode-Python-300. 最长上升子序列

本文介绍了一种算法,用于寻找无序整数数组中最长上升子序列的长度。通过动态规划方法,实现时间复杂度为O(n^2)的解决方案。文章详细解释了动态规划过程,并提供了两种不同实现思路的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

示例:

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

说明:

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

第一种思路:

用dp[i] 表示 从下标0 到下标i 的最长上升子序列的长度,

例如对于样例输入[10,9,2,5,3,7,101,18], 有 dp = [ 1, 1, 1, 2, 2, 3, 4, 4]。

显然dp[0] = 1

对于任意的i 不为零的情况,应该在 i 的左侧找一个下标 j ,其满足两个条件:

1. nums[ j ]比 nums[ i ] 小

2. 它是所有满足条件1里 dp [j]  最大的那个

dp[i] = max(dp[j]) + 1 , j < i and nums[ j ] < nums[ i ]

如果不存在这样的下标j,说明在0 ~ i - 1 的范围内,所有元素都比nums[i] 大,即无法找到一个能和 nums[i] 组成上升子序列的元素,所以dp[i] = 1, 表示为nums[i] 自身成为一个长度为1 的上升子序列。

class Solution(object):
    def lengthOfLIS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        l = len(nums)
        if not l:
            return 0
        dp = [1 for _ in range(l)]
        
        for index, item in enumerate(nums):
            dp[index] = self.find(nums[:index + 1], dp) + 1
        # print dp       
        return max(dp)
            
    
    def find(self, nums, dp):
        max_element = -1 * 2 << 31
        
        for i in range(len(nums) - 2, -1, -1):
            if nums[i] < nums[-1]:
                max_element = max(max_element, dp[i]) 

        return max_element if max_element != -1 * 2 << 31 else 0

#修改前的在下面:
class Solution(object):
    def lengthOfLIS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        l = len(nums)
        if not l:
            return 0
        dp = [0 for _ in range(l)]
        
        for index, item in enumerate(nums):
            if index == 0:
                dp[index] = 1
            else:
                val = self.findClosestSmallerElementInLeft(nums[:index + 1], dp)
                if val == -1:
                    dp[index] = 1
                else:
                    dp[index] = val + 1
        print dp       
        return max(dp)
            
    
    def findClosestSmallerElementInLeft(self, nums, dp):
        max_element = -1 * 2 << 31
        for i in range(len(nums) - 2, -1, -1):
            if nums[i] < nums[-1]:
                max_element = max(max_element, dp[i]) 
        # print nums[-1], max_element
        return max_element if max_element != -1 * 2 << 31 else -1

第二种思路:

从评论区学来的,思路差不多,但是实现会更加简洁。

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值