给定一个无序的整数数组,找到其中最长上升子序列的长度。
示例:
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
说明:
可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n2) 。
进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-increasing-subsequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
法一:“动态规划” 以当前位置元素为结尾作为状态,作为状态转移方程
dp[i]=max(dp[j])+1 if j<i and nums[i]>nums[j]
class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
# dp解决 状态:以当前i为结尾的最长递增子序列 dp[i]=max(dp[j])+1 if j<i and nums[i]>nums[j]
if not nums:return 0
n=len(nums)
if n==1:return 1
dp=[1]*(n)
for i in range(1,n):
temp=0
# 可改为二分查找 O(nlogn)
for j in range(i):
if nums[j]<nums[i]:
temp=max(dp[j],temp)
dp[i]=temp+1
return max(dp)
法二:但对于有序数组的查找,采用二分法 O(nlogn)
class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
# 定义一个二分查找
def binary_seach(nums,target):
'''
返回target在nums中按升序的位置
'''
n=len(nums)
i,j=0,n-1
while i<=j:
mid=(i+j)//2
if nums[mid]==target:return mid
elif nums[mid]<target:i=mid+1
else:j=mid-1
return i
if not nums:return 0
n=len(nums)
if n==1:return 1
# 记录当前最长递增序列
dp=[]
dp.append(nums[0])
max_len=1
for i in range(1,n):
if nums[i]<=dp[0]:
dp[0]=nums[i]
elif nums[i]>dp[-1]:
dp.append(nums[i])
max_len+=1
else:
temp=binary_seach(dp,nums[i])
dp[temp]=nums[i]
return max_len