zoukankan      html  css  js  c++  java
  • 动态规划-最长上升子序列

    问题描述一个数的序列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 """
  • 相关阅读:
    dedecms自定义表单提交获取时间跟ip地址
    JQuery购物车多物品数量的加减+总价计算
    jquery手机触屏滑动拼音字母城市选择器代码
    js实现图片上传实时显示
    js实现发送验证码倒计时效果
    JS 仿支付宝input文本输入框放大组件
    js实现倒计时效果
    jquery统计输入文字的个数并对其进行判断
    【Linux】Linux系统安全设置
    java泛型(generics)
  • 原文地址:https://www.cnblogs.com/an-wl/p/12921290.html
Copyright © 2011-2022 走看看