最长递增子序列(LIS)
LIS: longest increasing subsequence
分析:
O(n2)
O
(
n
2
)
的算法比较简单,这里就不说了,说一下
O(lg(n))
O
(
l
g
(
n
)
)
的做法。
假设有两个数组A和B,A为存储序列的数组,B:B[i]代表长度为i的递增子序列中最大元素的最小值。B的下标从1开始。
对A中的元素进行遍历,对A中的每一个元素key,在B中进行二分查找,找到第一个比key的元素,返回其下标j,若j大于B中现有元素个数cnt,说明B中现有的所有的递增子序列中最大元素的最小值不用改变,而key是长度为cnt+1的递增子序列中最大元素的最小值;否则,将B[j]替换为key,因为长度为j的递增子序列中最大元素的最小值可以变得更小,即为key。
因为使用了二分查找,所以时间为O(lgn).
代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
int A[101];
int B[101];
int LIS(int n){
int cnt = 1;
for (int i = 0; i < n; ++i){
if (i == 0){
B[cnt++] = A[0];
}
else{
int j = upper_bound(B + 1, B + cnt, A[i]) - B;
if (j >= cnt){
B[cnt++] = A[i];
}
else{
B[j] = A[i];
}
}
}
return cnt - 1;
}
int main(void){
int n;
cout << "请输入数字个数n:";
cin >> n;
for (int i = 0; i < n; ++i){
cin >> A[i];
}
int maxLen = LIS(n);
cout << maxLen << endl;
return 0;
}