Given an unsorted array of integers, find the length of longest increasing subsequence.
Example:
Input: [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
Note:
There may be more than one LIS combination, it is only necessary for you to return the length.
Your algorithm should run in O(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?
动态规划. 构造数组dp, dp[i]表示到i点时能构成的递增数组的长度, 初始化dp为值为1的数组, 状态转移方程为:
dp[i] = max(dp[i], dp[j]+1) if j < i and nums[j] < nums[i]
遍历nums, 对每个数字, 寻找它之前比它小的数字, 这样能构成递增数组, 更新dp[i], 最后返回数组dp的最大值即可.
Time: O(n**2)
Space: O(n)
class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
# base case
if not nums: return 0
dp = [1]*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)
二分搜索法. 构造sub, 表示当前的递增数列, 遍历nums, 找到如果n插入sub时, 它应该处在的位置. 如果pos == len(sub)表示n比sub里所有数都大, 直接加到sub中, 其他情况表示n<= sub[pos], 更新sub[pos]. 最后返回sub的长度即可.
class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
def binarySearch(sub, n):
# return the index of n for insertion
left, right = 0, len(sub)-1
while left <= right:
mid = (left+right)//2
if n == sub[mid]:
return mid
elif n > sub[mid]:
left = mid+1
else:
right = mid-1
return left
sub = []
for n in nums:
pos = binarySearch(sub, n)
if pos == len(sub):
sub.append(n)
else:
sub[pos] = n
return len(sub)
二分搜索法, 同解法2, 使用bisect.bisect_left()方法
class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
sub = []
for n in nums:
pos = bisect.bisect_left(sub, n)
if pos == len(sub):
sub.append(n)
else:
sub[pos] = n
return len(sub)