动态规划-最长上升子序列

问题描述一个数的序列ai,当a 1 < a 2 < ... < a S 的时候,
我们称这个序列是上升的。对于给定的一个序列(a 1 , a 2 , ..., a N ),
我们可以得到一些上升的子序列(a i1 , a i2 , ..., a iK ),
这里1 <= i1 < i2 < ... < iK<= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),
有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中
最长的长度是4,比如子序列(1, 3, 5, 8).

你的任务,就是对于给定的序列,求出最长上升子序列的长度(LIS)。
输入数据:输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给
出序列中的N个整数,这些整数的取值范围都在0到10000。
输出要求:最长上升子序列的长度。
输入样例
7
1 7 3 5 9 4 8
输出样例
4

解题思路:假设对n个数求最长子序列,利用动态规划的思想,可以转化为
求若干个子问题的过程,比如先求n-1的最子长序列,n-2,直到第1位数值。
理由是这样,n-1的最长子序列长度已经求得了,那么如果n比n-1大,那么
利用n加入这个子序列,所以长度+1,如果小,那么其子序列的长度就需要
找比n小的最大的子序列长度+1,一定要理解好这句话,因为比前面比n小
的有可能有多个数,但是要找到最大的那个,然后在其基础上+1,就能求出
n的最长子序列的长度。

Python算法实现:
 1 from random import randint
 2 
 3 # 生成指定长度的范围为[0, 1000]的整数列表
 4 
 5 
 6 def generate_integer_list(length):
 7     lst = []
 8     for i in range(length):
 9         lst.append(randint(0, 1000))
10     return lst
11 
12 
13 tempList = generate_integer_list(10)
14 # tempList = [206, 184, 197, 451, 912, 517, 321, 803, 446, 294]
15 # maxLength列表存储每个位置的最长子序列的长度,假设初始是1
16 maxLen = [1]*10
17 
18 # 每次求以第i个数为终点的最长上升子序列的长度
19 for i in range(1,10):
20     for j in range(0,i):
21         # 察看以第j个数为终点的最长上升子序列
22         if tempList[i] > tempList[j]:
23             maxLen[i] = max(maxLen[i],maxLen[j]+1)
24 
25 maxValue = max(maxLen)
26 indexPos = maxValue
27 outList = []
28 start = len(maxLen)-1
29 while indexPos > 0:
30     for k in range(start, -1, -1):
31         if maxLen[k] == indexPos:
32             outList.append(tempList[k])
33             # 往每次从找到匹配最大值的元素的前面查找,不能每次都从后往前找
34             start = k
35             break
36     indexPos -= 1
37 print("原列表为:",end="")
38 print(tempList)
39 print("最长子序列为:%d" % maxValue)
40 print("其中一个最长子序列为:",end="")
41 outList.reverse()
42 print(outList)
43 
44 
45 """
46 # 利用bisect进行二分查找
47 from bisect import bisect
48 def longest_inc_sub(seq):
49     end = []
50     for su in seq:
51         # 查找su在end列表中的位置
52         idx = bisect(end, su)
53         if idx == len(end):
54             end.append(su)
55         else:
56             end[idx] = su
57     return len(end)
58 nums = [10, 6, 19, 23, 31, 20, 8]
59 print(longest_inc_sub(nums))
60 """
61 
62 """
63 def lis(arr):
64     n = len(arr)
65     m = [0] * n
66     for x in range(n - 2, -1, -1):
67         for y in range(n - 1, x, -1):
68             if arr[x] < arr[y] and m[x] <= m[y]:
69                 m[x] += 1
70         max_value = max(m)
71         result = []
72         for i in range(n):
73             if m[i] == max_value:
74                 result.append(arr[i])
75                 max_value -= 1
76     return result
77 
78 arr = [10, 22, 9, 33, 21, 50, 41, 60, 80]
79 print(lis(arr))
80 """

 

posted @ 2020-05-20 08:00  StudyNLP  阅读(448)  评论(0编辑  收藏  举报