//求最长递增子序列的方法有很多,下面就我接触到的三种方法来写一下实现代码:第一种方法是DP,
//第二种是DP+二分查找,第三种是转换为求LCS的方法!而第二种的时间复杂度占优势:O(nlogn)!
//第一种方法的DP代码:
#include <iostream>
using namespace std;
const int MAX = 100000;
int dp[MAX];
int main()
{
//n为元素的个数
int i, j, tmp, n, num[100000], lis_len = 0;
while (cin >> n){
for (i = 0; i < n; i++){
cin >> num[i];
}
//时间复杂度为O(n^2)的dp法
for (i = 0; i < n; i++){
dp[i] = 1;
for (j = 0; j < i; j++){
if (num[j] < num[i] && dp[i] < dp[j] + 1){
dp[i] = dp[j] + 1;
}
if (dp[i] > lis_len)
lis_len = dp[i];
}
}
//for (i = 0; i < n; i++)
// cout << dp[i] << " ";
//cout << endl;
cout << lis_len << endl;
}
system("pause");
}
//第二种方法是二分查找+DP的方法!
#include <iostream>
using namespace std;
const int MAX = 100000;
int num[MAX], tmp[MAX];
int main()
{
int i, n, left, right, mid, ans;
while (cin >> n){
for (i = 0; i < n; i++){
cin >> num[i];
}
ans = 0;
tmp[0] = -1;
for (i = 0; i < n; i++){
if (num[i] > tmp[ans]){
tmp[++ans] = num[i];
}
//二分查找,找出次小的数的位置,然后再插入数组中
else{
left = 1, right = ans;
while (left <= right){
mid = (left + right) / 2;
if (num[i] > tmp[mid]){
left = mid + 1;
}
else{
right = mid - 1;
}
}
tmp[left] = num[i];
}
}
//for (i = 1; i <= ans; i++)
//cout << tmp[i] << " ";
//cout << endl;
cout << ans << endl;
}
system("pause");
}
//第三种方法转化为LCS方法,将一个数组的数进行递增的排序之后,显然就可以通过求
//原数组在通过排序之后的数组中的最长公共子序列了!
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX = 10000;
int dp[MAX][MAX], flag[MAX][MAX];
int num[MAX], tmp[MAX];
void printLIS(int arr[][MAX], int *arrnum, int i, int j)
{
if (i == 0 || j == 0)
return ;
if (arr[i][j] == 0){
printLIS(arr, arrnum, i-1, j-1);
cout << arrnum[i-1] << " ";
}
else if (arr[i][j] == 1){
printLIS(arr, arrnum, i-1, j);
}
else{
printLIS(arr, arrnum, i, j-1);
}
}
int main()
{
int i, j, n;
while (cin >> n){
for (i = 0; i < n; i++){
cin >> num[i];
tmp[i] = num[i];
}
sort(tmp, tmp+n);//通过排序,使其数组成为递增的序列
memset(dp, 0, sizeof(dp));
memset(flag, 0, sizeof(flag));
for (i = 1; i <= n; i++){
for (j = 1; j <= n; j++){
if (num[i-1] == tmp[j-1]){
dp[i][j] = dp[i-1][j-1] + 1;
flag[i][j] = 0;
}
else if (dp[i-1][j] > dp[i][j-1]){
dp[i][j] = dp[i-1][j];
flag[i][j] = 1;
}
else{
dp[i][j] = dp[i][j-1];
flag[i][j] = -1;
}
}
}
printLIS(flag, num, n, n);
cout << endl;
cout << dp[n][n] << endl;
}
system("pause");
}
/*
7
1 7 3 5 9 4 8
*/
最长递增子序列(LIS)的三种求解方法
最新推荐文章于 2020-05-09 23:10:51 发布