您的位置:首页 > 产品设计 > UI/UE

leetcode -- Longest Increasing Subsequence -- DP 重点常考

2015-12-14 18:01 597 查看
https://leetcode.com/problems/longest-increasing-subsequence/

思路1 n^2

参考http://bookshadow.com/weblog/2015/11/03/leetcode-longest-increasing-subsequence/

动态规划(Dynamic Programming)

状态转移方程:

dp[x] = max(dp[x], dp[y] + 1) 其中 y < x 并且 nums[x] > nums[y]


即在求dp[x]的时候,比较x之前的元素y以及其对应的dp[y], 找到一个最大的dp[y] + 1, y

class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
size = len(nums)
dp = [1] * size
for x in range(size):
for y in range(x):
if nums[x] > nums[y]:
dp[x] = max(dp[x], dp[y] + 1)
return max(dp) if dp else 0


思路2 nlogn

binary search

这里类似于插入排序,这里用BS不是找到一个target数的index,而是找到一个target所能插入的index。所以不返回mid, 返回low,并且也不用对等号进行判断。

就是用dp数组来维护一个升序数组,scan每一个数组值A[i],然后看A[i]是否能插入dp中,如果low >=len(dp), 那么就在dp末尾append; else 则替换dp[low] = A[i],因为这样替换并没有降低当前LIS的长度,并且还扩大increasing subsequence长度的增长空间

本质就是如果是个可以插入的值,例如dp = {2, 5}, A[i] = 3, 则替换最后一个值,降低increasing subsequence的最大值以扩大increasing subsequence长度的增长空间;如果A[i] = 6, 无法插入,那么就直接加入在dp末尾就行。这里如果只对,low>=len(dp)在dp末尾append,那么就不能修改搜索递增序列的最小值,使得[10,9,2,5,3,7,101,18]这样的输入,得到的结果是[10, 101]

这是一个trick。记住

code 参考 http://bookshadow.com/weblog/2015/11/03/leetcode-longest-increasing-subsequence/

class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
size = len(nums)
dp = []
for x in range(size):
low, high = 0, len(dp) - 1
while low <= high:
mid = (low + high) / 2
if dp[mid] >= nums[x]:
high = mid - 1
else:
low = mid + 1
if low >= len(dp):
dp.append(nums[x])
else:#这里在dp = [2,3], nums[x] = 1的情况下,会将dp变成[1,3], 虽然不是递增的seq,但是长度一样。
dp[low] = nums[x]
return len(dp)


自己重写code

class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if len(nums) == 0: return 0
lis = []
for i in xrange(len(nums)):
if lis == []:
lis.append(nums[i])
else:
low, high = 0, len(lis) - 1
while low <= high:
mid = (low + high) / 2
if lis[mid] < nums[i]:#这里不要有等号
low = mid + 1
else:#等号放在这里,因为lis = [2], nums[i] = [2],这样的case不应该变成[2,2]
high = mid - 1
if low == len(lis):#不是low == i
lis.append(nums[i])
else:
lis[low] = nums[i]
return len(lis)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: