300. 最长上升子序列(Longest Increasing Subsequence)
2020-01-14 18:13
459 查看
300. 最长上升子序列(Longest Increasing Subsequence)
题解
动态规划
dp[i]dp[i]dp[i]表示到当前位置的最长上升子序列的长度。
-
特判,若数组为空,返回0
-
初试化dp=[1,1,⋯ ,1]dp=[1,1,\cdots,1]dp=[1,1,⋯,1],长度为nnn,dp[i]=1dp[i]=1dp[i]=1表示每一位都可以为长度为1的最长上升子序列。
-
遍历dpdpdp,对于iii,遍历区间[1,n)[1,n)[1,n):
-
遍历当前位置前的所有位置jjj,遍历区间[0,i)[0,i)[0,i):
若nums[i]>nums[j]nums[i]>nums[j]nums[i]>nums[j],表示满足上升的条件。此时,更新当前位置的最长上升子序列的长度:dp[i]=max(dp[i],dp[j]+1)dp[i]=max(dp[i],dp[j]+1)dp[i]=max(dp[i],dp[j]+1)。
-
返回dpdpdp中的最大值。
复杂度分析
- 时间复杂度:O(n2)O(n^{2})O(n2)
- 空间复杂度:O(n)O(n)O(n)
Python
class Solution: def lengthOfLIS(self, nums: List[int]) -> int: if(not nums): return 0 n=len(nums) dp=[1]*n for i in range(n): for j in range(i): if(nums[i]>nums[j]): dp[i]=max(dp[i],dp[j]+1) return max(dp)
Java(待完成)
动态规划+二分查找
定义tailtailtail数组,tail[i]tail[i]tail[i]保存遍历过程中长度为i+1i+1i+1的最长上升子序列的最小尾元素。
tailtailtail本身要求严格递增。
最终tailtailtail的长度就是整个数组最长上升子序列的长度。
解释:
这里长度等于最长上升子序列的长度,但是tailtailtail不一定为最长上升子序列。
- 特判,若数组长度小于222,返回数组长度。
- 初始化tail=[nums[0]]tail=[nums[0]]tail=[nums[0]],表示目前为止长度为1的最长上升子序列的最小尾元素为nums[0]nums[0]nums[0]
- 遍历数组,对于iii,遍历区间[1,n)[1,n)[1,n):
-
若nums[i]>tail[−1]nums[i]>tail[-1]nums[i]>tail[−1],tail[−1]tail[-1]tail[−1]表示最后一个元素。若当前的数组元素比tailtailtail的最后一个元素大,将其加入tailtailtail。跳过后续步骤。
- 若不满足,则在tailtailtail中找到第一个比他大的元素,替换掉。使用二分查找,查找替换位置。
- 定义左界l=0l=0l=0,右界r=len(tail)−1r=len(tail)-1r=len(tail)−1
- 进入循环,循环条件l<=rl<=rl<=r: 定义mid=(l+r)//2mid=(l+r)//2mid=(l+r)//2
- 若nums[i]<=tail[mid]nums[i]<=tail[mid]nums[i]<=tail[mid],更新右界:r=mid−1r=mid-1r=mid−1
- 否则,l=mid+1l=mid+1l=mid+1
- 替换,tail[l]=nums[i]tail[l]=nums[i]tail[l]=nums[i]
- 返回tailtailtail的长度。
复杂度分析
- 时间复杂度:O(nlog(n))O(nlog(n))O(nlog(n))
- 空间复杂度:O(n)O(n)O(n)
Python
class Solution: def lengthOfLIS(self, nums: List[int]) -> int: if(not nums): return 0 n=len(nums) if(n<2): return n tail=[nums[0]] for i in range(1,n): if(nums[i]>tail[-1]): tail.append(nums[i]) continue l=0 r=len(tail)-1 while(l<=r): mid=(l+r)//2 if(tail[mid]>=nums[i]): r=mid-1 else: l=mid+1 tail[l]=nums[i] return len(tail)
Java(待完成)
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- 最长上升子序列(Longest Increasing Subsequence)
- *[Lintcode]Longest Increasing Subsequence 最长上升子序列
- 最长上升子序列LIS(Longest increasing subsequence)
- leetcode(300)—— Longest Increasing Subsequence(最长递增子序列)
- Longest Increasing Subsequence[LIS 最长上升子序列问题] (Longest Ordered Subsequence) POJ - 2533 队列优化
- 动态规划--最长上升子序列(Longest increasing subsequence)
- 【LeetCode 300 Longest Increasing Subsequence】最长递增子序列
- nlog(n)解动态规划--最长上升子序列(Longest increasing subsequence)
- Leetcode 300 Longest Increasing Subsequence 最长递增子序列
- 最长上升子序列LIS(Longest Increasing Subsequence)
- poj2533-Longest Ordered Subsequence(最长上升子序列)
- Longest Ordered Subsequence与最少拦截系统 DP+贪心(最长上升子序列及最少序列个数)
- 【poj 2127】Greatest Common Increasing Subsequence 最长公共上升子序列lics+路径打印
- 最长上升子序列 Longest Increasing Subsequence 输出其中一个序列 O(n^2) O(nlogn)
- LIS(Longest Increasing Subsequence)最长上升(不下降)子序列
- poj 2533 Longest Ordered Subsequence (最长上升子序列)
- hdu 1423 Greatest Common Increasing Subsequence (最长上升子序列)
- 最长上升子序列 LIS (Longest Increasing Subsequence)
- POJ2533 -Longest Ordered Subsequence最长上升子序列-动规和nlogn二分算法详解
- LIS(Longest Increasing Subsequence)最长上升(不下降)子序列