您现在的位置是:主页 > news > 顺德新网站制作/seo网络推广课程
顺德新网站制作/seo网络推广课程
admin2025/5/25 5:55:18【news】
简介顺德新网站制作,seo网络推广课程,广州十大游戏公司,版式设计作品集定义 最长上升子序列(Longest Increasing Subsequence,LIS),在计算机科学上是指一个序列中最长的单调递增的子序列。 问题描述 给定一个长度为 N 的数组,找出一个最长的单调自增子序列(不一定连续&#…
定义
最长上升子序列(Longest Increasing Subsequence,LIS),在计算机科学上是指一个序列中最长的单调递增的子序列。
问题描述
给定一个长度为 N 的数组,找出一个最长的单调自增子序列(不一定连续,但是顺序不能乱)。例如:给定一个长度为 5 的数组{5, 6, 1, 2, 8},则其最长的单调递增子序列为 {5,6,8},长度为 3。
解法
动态规划
时间复杂度
该方法的时间复杂度为 。
实现过程
下面我们用一个实例来分析一下动态规划求解 LIS 的整个过程。假设数组 A 的内容为 {5, 6, 1, 2, 8}。
1、第一个元素直接设置 LIS 长度为 1 即可。如下图所示。
2、第二个元素 6 大于前面所有元素进行比较。5<6,则 LIS[1] = LIS[0]+1 = 2。如下图所示。
3、第三个元素 1 和前面的所有元素进行比较。1<6,则 LIS 的长度可能为 1;1<5,则 LIS 的长度可能为 1;取最大值,LIS[2]=1 。如下图所示。
4、第四个元素 2 和前面的所有元素进行比较。1<2,则 LIS 的长度可能为 LIS[2]+1 = 2;6>2,则 LIS 的长度可能为 1;5>2,则 LIS 的长度可能为 1;取最大值,LIS[3]=2 。如下图所示。
5、第五个元素 8 和前面的所有元素进行比较。2<8,则 LIS 的长度可能为 LIS[3]+1 = 3;8>1,则 LIS 的长度可能为 LIS[2]+1 = 2;8>6,则 LIS 的长度可能为 LIS[1]+1 = 3;8>5,则 LIS 的长度可能为 LIS[0]+1 = 2;取最大值,LIS[4]=3 。如下图所示。
算法思路
设长度为 N 的数组为 {a0,a1, a2, ..., an-1),则假定以 aj 结尾的数组序列的最长递增子序列长度为 LIS(j),则 LIS(j) = {max(LIS(i))+1, i<j 且 a[i] < a[j] }。
二分查找
时间复杂度
该方法的时间复杂度为 。
算法描述
我们可以引入一个新数组 maxV,该数组的特性为:
长度为 1 的递增子序列最大元素的最小值为 maxV[1];
长度为 2 的递增子序列最大元素的最小值为 maxV[2];
…
长度为 LIS[i] 的递增子序列最大元素的最小值为 maxV[LIS[i]]。
首先,证明 maxV[] 是递增的,因此可以使用二分搜索。我们可以用数学归纳法即可证明:若前 k 个元素是递增的,一定有 。
证明:假设不成立,则 maxV[k+1] < maxV[k]。
根据 maxV[k+1] 的定义,存在一个长度是 k+1 的 LIS,并且以 maxV[k+1] 为最大元素。将上述子序列去掉最后一个元素maxV[k+1], 得到长度为 k,且最大元素 < maxV[k+1] < maxV[k]。
这显然与 maxV[k] 的定义矛盾。所以假设不成立。
实现过程
我们用一个实例来分析一下二分查找求解 LIS 的整个过程。假设数组 A 的内容为 {5, 6, 1, 2, 8}。
我们用 LIS[i-1] 表示长度为 i 的最长递增子序列末尾的数据。
1、第一个元素直接加入到 LIS 数组中。LIS[0]=5,表示长度为 1 的 LIS 数组最后一个元素是 5。如下图所示。
2、第二个元素为 6,因为 6>LIS[0],构成递增,将数字 6 加入到 LIS 数组中,即 LIS[1]=6,表示长度为 2 的 LIS 数组的末尾是 6。如下图所示。
3、第三个元素为 1,1<LIS[2],因此前面一定有一个位置的数据可以换成 1,并且后面的递增性质不会被破坏。因此我们使用二分查找在 LIS 数组中找到 1 的位置,我们知道 lower_bound 查找的位置为 0。也就是说 LIS[0] 可以被替换为 1。如下图所示。
4、第四个元素为 2,2<LIS[2],因此前面一定有一个位置的数据可以换成 2,并且后面的递增性质不会被破坏。因此我们使用二分查找在 LIS 数组中找到 2 的位置,我们知道 lower_bound 查找的位置为 1。也就是说 LIS[1] 可以被替换为 2。如下图所示。
4、第五个元素为 8,8>LIS[2],构成递增,将数字 8 加入到 LIS 数组中,即 LIS[2]=8,表示长度为 3 的 LIS 数组的末尾是 8。如下图所示。
这样,我们完成了遍历,这时候我们可以发现 LIS 数组的小标为 2,表示我们要求解的 LIS 长度为 3。
算法思路
将 array[i] 在当前的 maxV[] 数组中进行二分搜索,找到位置 k,maxV[k] < array[i] < maxV[k+1]。
将 array[i] 加入 maxV[] 数组。仅仅影响 maxV[k+1] (maxV[k+1] = array[i]),而对其他的元素不产生影响。
参考实现
int LIS(int *a, int n) {if (n<=0) {return 0;}vector<int> maxV;maxV.push_back(a[0]);for(int i=1; i<n; ++i) {if (a[i] > *maxV.rbegin()) {maxV.push_back(a[i]);} else {*lower_bound(maxV.begin(), maxV.end(), a[i]) = a[i];} }return maxV.size();
}