【动态规划-中等】300. 最长递增子序列

这篇博客讨论了如何解决寻找整数数组中最长严格递增子序列的问题。提供了三种不同的方法,包括动态规划、贪心和二分查找。动态规划方法通过dp数组记录以每个数字结尾的最长子序列长度;贪心方法通过维护一个递增序列列表来找到答案;二分查找方法在已有的递增序列中插入新数字,优化了时间复杂度。所有方法的时间复杂度都在O(nlog(n))内。

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

题目
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

示例 1:

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

示例 2:

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

示例 3:

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

提示:

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

进阶:

你可以设计时间复杂度为 O(n2) 的解决方案吗?
你能将算法的时间复杂度降低到 O(n log(n)) 吗?

【代码】
【方法1:动态规划】
在这里插入图片描述使用dp[i]记录nums[i]结尾的元素最长的序列长度
定义 dp[i] 为考虑前 i 个元素,以第 i 个数字结尾的最长上升子序列的长度

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        dp=[1 for i in range(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)

【方法2】
在这里插入图片描述

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        ans=[]
        for num in nums:
            flag=False
            for index,item in enumerate(ans):
                if item[-1]>=num:
                    ans[index].append(num)
                    flag=True
                    break
            if not flag:
                ans.append([num])
        return len(ans)

【方法3:贪心+二分】
在这里插入图片描述

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        ans=[]
        for num in nums:
            if not ans or num>ans[-1]:
                ans.append(num)
            else:
                low,high=0,len(ans)-1
                loc=high
                while low<=high:
                    mid=(low+high)//2
                    if ans[mid]>=num:
                        loc=mid
                        high=mid-1
                    else:
                        low=mid+1
                ans[loc]=num
        return len(ans)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值