N久没有更新博客了,主要是因为科研任务繁重= =,自己又很菜B,所以没有时间锻炼作为码农的基本素养:Coding。
周末抽空来随机找一个题目练练手。就看到了曾经处理过的动规的经典LIS。以前不理解,现在已经能够理解了。但是要说精髓部分,还是需要经过各种花式训练,
估计才能理解的更加深刻 。
题目连接:
https://leetcode.com/problems/longest-increasing-subsequence/
确保每个序列的美中可能都包含考虑了。
那么每个状态d(n)的含义就是。以num[n]结尾的最长LIS。
那么就考虑当前拿到的数与num[n]能否构成新的LIS,即考虑能否+1.
所有对于d[5], 6 前面有三个比它小的,8比它大,直接构不成,就不考虑。对于所谓考虑漏过8构成LIS的,直接在前面的d[x]中考虑了。
构不成还是要考虑的, 就是不加上1的考虑。
还是要不考虑比当前数字大的LIS,因为考虑了就没有办法形成连贯性的加法。
以上两句话,是我纠结的过程。= =
d[5] = max{d[1], d[2], d[3] } + 1.
对于d[6] = max{d[1],d[2], d[3], d[5]} + 1
好的,那么问题就简单了。
class Solution(object):
def lengthOfLIS(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if len(nums) == 0:
return 0;
if len(nums) == 1:
return 1
d = [1 for i in range(len(nums))]
for i in range(1,len(nums)):
dmax = -1
for j in range(0,i):# find satisfy the less condition and d[] array bigger.
if nums[j] < nums[i] and d[j] > dmax:
dmax = d[j]
# if there is some number less than current number
if dmax + 1> d[i]:
d[i] = dmax + 1
finalMax = -1
for each in d:
if each > finalMax:
finalMax = each
return finalMax
so = Solution()
print so.lengthOfLIS([1,3,6,7,9,4,10,5,6])
代码一出来。
还是有几个编码过程中的错误:
1. 对动态规划中,递归数据理解的不准确。对于迭代推导的d[]数组中的值而言,它就表达的是以对应索引位置的数字结尾的、且该数字必须作为LIS序列一部分的、最长的LIS。 不能说可以绕过前面的数据而构成,比如 1,2,8,9,5.
作为5而言,这个位置的d[]数组,就是3 (1,2,5)。而不是说不使用当前数字5构成的4 (1,2,8,9,)。
2. 对最终返回的最长LIS选择错误。误以为d[]数组中最后一个是最大的,其实不是。基于上述对于d[]数组的理解,相信不难推导出从中选择最大的。
总结:动规这个东西,以前总是不理解,现在好在能够理解一些了。它的思想还是大化小。要理解内涵,觉得就是要理解每个状态所表达的意思。