300. 最长上升子序列
300. 最长上升子序列
题意
给定一个无序的整数数组,找到其中最长上升子序列的长度。
解题思路
动态规划:看到这种题目首先想到的就是dp,受到之前最长回文子串的影响,也以为是要用二维数组来解,然后用(i,j)记录区间的最长值,后来发现完全没有必要。
假设dp[i]表示0到i中的最长序列长度,如果之前的值比当前值小,则说明之前的值和当前值构成一个递增序列,所以状态转移方程为:
dp[cur] = max(dp[cur], dp[i] + 1) (if i < cur and nums[cur] > nums[i])
二分查找:维护一个有序序列,如果当前值在这个有序序列中排在最后面,说明当前值加入到有序序列中依然有序,否则则进行替换,时间复杂度为O(nlogn);
实现
class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
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)
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
dp = [] # 维护一个最长的有序数组
for i in range(len(nums)):
low, high = 0, len(dp)
# 判断nums[i]在数组中是否有序
while low < high:
mid = (low + high) // 2
if nums[i] > dp[mid]:
low = mid + 1
else:
high = mid
# 如果值的位置在最后,插入后依旧保持有序,相反,则替换掉原来位置的值
if low >= len(dp):
dp.append(nums[i])
else:
dp[low] = nums[i]
return len(dp)
![](https://i.loli.net/2018/11/17/5beff4d639cbb.jpg)
关注公众号:数据结构与算法那些事儿,每天一篇数据结构与算法