最长非递减子序列,Python实现

python 复制代码
from time import time
from bisect import bisect
from random import choices, seed
from itertools import combinations

def func1(seq):
    # 暴力穷举,从最长的子序列开始查找,大约耗时5小时
    for n in range(len(seq)-1, 0, -1): # 依次查找长度为len(seq-1),len(sqe-1)-1,....3,2,1
        for sub in combinations(seq,n): # 枚举出seq中所有的长度为n的序列,元素原来的先后顺序不变
            if list(sub) == sorted(sub):
                return sub              # 因为是从最长向最短判断的,产生返回的肯定是长度最长的
                
def func2(seq):
    # 获取可能的最大长度,缩小后面循环的范围,大约耗时1小时
    # 比fun1的优点是先判断出最大可能长度
    m = 0
    for i in range(len(seq)-1):
        if seq[i+1]>seq[i]:
            m = m+1
    if seq[-1] > seq[-2]:
        m = m+1
    for n in range(m+1, 0, -1):
        for sub in combinations(seq, n):         
            if list(sub) == sorted(sub):
                return sub
                
def func3(seq):
    # 查找最长非递减子序列的长度,直接确定后面组合时的长度,4秒
    # 动态规划法,查表
    length = [1]*len(seq)
    for index1, value1 in enumerate(seq):   # 如果前面有更小的元素,就更新当前元素为终点的子序列长度
        for index2 in range(index1):
            if seq[index2] <= value1:   # 存在前面数小于本轮待比较数
                length[index1] = max(length[index1], length[index2]+1) # 迭代是从0开始的,length最小的序号会最先确定长度
    m = max(length)
    for sub in combinations(seq, m):
        if list(sub) == sorted(sub):
            return sub
                
def func4(seq):
    # 查找最长非递减子序列的长度,直接确定后面组合时的长度,3.66秒
    # 比func3的优点时,先排除掉无效子序列,减少第2步比较数量
    length = [1]*len(seq)
    for index1, value1 in enumerate(seq):
        for index2 in range(index1):
            if seq[index2] <= value1:
                length[index1] = max(length[index1], length[index2]+1)
    m = max(length)
    for sub in combinations(seq, m):
    # 测试每个子序列中是否有违反顺序的相邻元素,避免对整个子序列排序
        for i,v in enumerate(sub[:-1]):
            if sub[i] > sub[i+1]:
                break
        else:
            return sub

def func5(seq):
    # 查找最长非递减子序列的长度,直接确定后面组合时的长度,3.7秒
    # [7,1,2,5,3,4,0,6,2]
    # sub = [1,2,3,4,6]
    # sub = [7]
    # sub = [1]
    # sub = [1,2,5]
    # sub = [1,2,3]
    # sub = [1,2,3,4]
    # sub = [0,2,3,4]
    # sub = [0,2,3,4,6]
    # sub = [0,2,3,4,6]
    sub = []
    m = 0
    # 循环结束后,m为最大非递减序列的长度,但sub并不是要求的子序列
    for value in seq:
        index = bisect(sub, value) # 使用bisect,要求sub必须为有序排列
        if index == m:
            sub.append(value)
            m = m + 1
        else:
            sub[index] = value
    for sub in combinations(seq, m):
        # 测试每个子序列中是否有违反顺序的相邻元素,避免对整个子序列排序
        for i,v in enumerate(sub[:-1]):
            if sub[i] > sub[i+1]:
                break
        else:
            return sub
            
def func6(seq):
    # 空间换时间,用来存放当前元素为终点的非递减子序列(暂未理解)
    sub = [[num] for num in seq]
    for index1, value1 in enumerate(seq[1:], start=1):
        for index2 in range(index1):
            if seq[index2] <= value1:
                for each in sub[index2]:
                    if isinstance(each, int):
                        each = [each]
                    sub[index1].append(each + [value1])
        # 只保留以当前元素为终点的最长非递减子序列
        sub[index1][1:] = [max(sub[index1][1:], default=[], key=len)]
    sub = list(map(lambda items: max(items[1:],default=[],key=len),sub))
    return max(sub, key=len)


def main():
    seed(20231106)  # 填充种子,随机生成数据相同
    data = choices(range(1000), k = 35) # 从0-9999数据中随机取35个数据
    for func in (func3,func4,func5,func6):
        start = time()  # 取LNDS前时刻
        for _ in range(1):
            r = func(data)  # 类似与函数指针
        print(time()-start) # 打印取数耗时,单位ms
        print(r)            # 打印LNDS
        
if __name__ == '__main__':
    main()

引用位置(不带注释):周末花了10小时把最长非递减子序列算法速度提高了几十亿倍

相关推荐
SsummerC2 分钟前
【leetcode100】组合总和Ⅳ
数据结构·python·算法·leetcode·动态规划
Tandy12356_9 分钟前
Godot开发2D冒险游戏——第一节:主角登场!
python·游戏引擎·godot
普if加的帕21 分钟前
java Springboot使用扣子Coze实现实时音频对话智能客服
java·开发语言·人工智能·spring boot·实时音视频·智能客服
安冬的码畜日常1 小时前
【AI 加持下的 Python 编程实战 2_10】DIY 拓展:从扫雷小游戏开发再探问题分解与 AI 代码调试能力(中)
开发语言·前端·人工智能·ai·扫雷游戏·ai辅助编程·辅助编程
西柚小萌新1 小时前
【Python爬虫基础篇】--4.Selenium入门详细教程
爬虫·python·selenium
朝阳5811 小时前
Rust项目GPG签名配置指南
开发语言·后端·rust
朝阳5812 小时前
Rust实现高性能目录扫描工具ll的技术解析
开发语言·后端·rust
程高兴2 小时前
基于Matlab的车牌识别系统
开发语言·matlab
橘猫云计算机设计2 小时前
springboot基于hadoop的酷狗音乐爬虫大数据分析可视化系统(源码+lw+部署文档+讲解),源码可白嫖!
数据库·hadoop·spring boot·爬虫·python·数据分析·毕业设计
YOULANSHENGMENG2 小时前
linux 下python 调用c++的动态库的方法
c++·python