300. 最长递增子序列
给你一个整数数组 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))
吗?
O(NlogN)
class Solution { public int lengthOfLIS(int[] nums) { int maxL=0; int[] dp=new int[nums.length];//所有长度为i+1的递增子序列中, 最小的那个序列尾数. //由定义知dp数组必然是一个递增数组, 可以用 maxL 来表示最长递增子序列的长度. for(int num:nums){ int index=Arrays.binarySearch(dp,0,maxL,num); if(index<0)index=-(index+1); dp[index]=num;//将num添加入dp数组尾部 if(index==maxL)maxL++;//表示num比所有已知递增序列的尾数都大,将最长递增序列长度maxL加1 } return maxL; } }
O(N^2)
class Solution: def lengthOfLIS(self, nums: List[int]) -> int: n=len(nums) if n==0: return 0 dp=[1]*n#dp[i] 表示以 nums[i] 结尾的最长上升子序列的长度 ans=1 for i in range(n): for j in range(i): #遍历到 nums[i] 的时候,我们应该把下标区间 [0, ... ,i - 1] 的 dp 值都看一遍 #如果当前的数 nums[i] 大于之前的某个数,那么 nums[i] 就可以接在这个数后面形成一个更长的上升子序列 if nums[i]>nums[j]: dp[i]=max(dp[i],dp[j]+1)#把前面的数都看了, dp[i] 就是它们的最大值加 1。即比当前数要小的那些里头,找最大的,然后加 1 。 ans=max(ans,dp[i]) return ans