使用分而治之找到最长的递增子序列
Posted
技术标签:
【中文标题】使用分而治之找到最长的递增子序列【英文标题】:Finding longest increasing sub-sequence using divide and conquer 【发布时间】:2016-12-08 15:04:00 【问题描述】:上周在一次采访中,我被问到上述问题,正如预期的那样,我无法正确回答,后来当我检查时,我发现它是一个基于动态编程的算法。我不精通动态编程,但假设我要设计这个算法,那么我应该如何处理它?
假设,我从 MergeSort 等其他分而治之的算法中汲取灵感,并设计如下解决方案:
-
将序列分成相等的两半。
找出两半中最长的递增子序列
加入两半。
明明还有缺的,怎么从这里往前走呢?
【问题讨论】:
我不明白,您只想在任何给定问题上应用随机想法并使其发挥作用?这个问题可以通过多种方式解决,但只有少数是自然的,动态编程就是其中之一,虽然显然不是最好的(高效) @Yerken 据我所知,使用 B-search 对 DP 版本进行了改进,实现了 O(nlgn),有没有更有效的 LIS 问题算法? @Yerken 这不是一个随机的想法,分而治之是一种众所周知的技术,其次,我的基本目标是知道锄头来解决对你来说完全陌生的问题。 @shole 我相信解决这个问题的效率最高。至少我不知道更快的方法。 @shole 假设您正在使用整数,如果您使用 van Emde Boas 树而不是二进制搜索,则可以在 O(n * lg(lg(n))) 时间内完成,并且通过额外的密钥重命名(如here 所述),它可以减少到 O(n * lg(lg(k))) 时间,其中 k 是 LIS 的长度。据我所知,这是已知最快的算法。 【参考方案1】:您的建议不会奏效,因为两半中最长的序列通常不连续,并且当您加入两半时可能存在更长的序列。
您可以按以下方式解决此问题:
在两半中,找到最长的递增子序列,设L和R;
在两半中,找到最长的左对齐递增子序列,令LL和RL;
在两半中,找到右对齐的最长递增子序列,设LR和RR;
对于最长的,如果L、R、LR+RL形成递增序列,则保留最长的;
对于左对齐,如果形成一个递增子序列,则保留 LL 或整个左子序列 + RL;
对于右对齐,如果这形成一个递增的子序列,则保留 RR 或 LR + 整个右子序列。
所有这些操作都在一个递归过程中完成。当你连接两个子序列时,检查它们是否形成一个递增的子序列只需要比较面对的元素。
更新:
这个“修复”没有彻底检查。
【讨论】:
以上是关于使用分而治之找到最长的递增子序列的主要内容,如果未能解决你的问题,请参考以下文章
算法实践--最长递增子序列(Longest Increasing Subsquence)
2021-11-16:最长递增子序列的个数。给定一个未排序的整数数组,找到最长递增子序列的个数。注意: 给定的数组长度不超过 2000 并且结果一定是32位有符号整数。力扣673。