您的位置:首页 > 其它

动态规划之最长上升子序列(未完待续)

2018-03-29 16:42 309 查看

动态规划之最长上升子序列(未完待续)

问题描述

输入数据

输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出

序列中的N个整数,这些整数的取值范围都在0到10000。

输出要求

最长上升子序列的长度。

输入样例

7

1 7 3 5 9 4 8

输出样例

4

输入样例

9

2 7 1 5 6 4 3 8 9

输出样例

5

解法一:递归式

在这里遇到了障碍

#include<iostream>
#define MAX 1000
using namespace std;
int a[MAX];

int has_smaller(int n)
{
int i = 0;
for(i = n-1; i>=0; i--)
{
if(a[i] <= a
)
return i;
}
return -1;
}

/* Longest increasing subsequence
*******************************
not finished yet!
*******************************
*/
int LIS(int n)
{
int i = has_smaller(n);
int j = 0;
if(i == -1)
return 1;
return LIS(i) + 1;
}

int main()
{
int n = 0;
int i = 0;
cin >> n;
for(i = 0; i<n; i++)
{
cin >> a[i];
}
cout << LIS(n-1)<<endl;
return 0;
}


解法二:递推式

对于每一个元素a[i]而言,len[i] = len(z) + 1 , j<=i且a[j] <=a[i],而z是所有满足条件的j中len(j)最大的那一个。若不存在满足上述条件的j,则len(i) = 1。

#include<iostream>
#define MAX 10005

using namespace std;

int a[MAX];
int b[MAX];

// longest increasing subsequence
void LIS(int n)
{
int i= 0;
int j = 0;
int sign = 0;
for(i = 0; i<n; i++)
{
sign = 0;
for(j = i-1; j>=0; j--)
{
if(a[j]<a[i] && b[j]>=b[i])
{
b[i] = b[j];
sign = 1;
}
}
if(sign == 1)
b[i]++;
}
}

int main()
{
int n = 0;
int result = 0;
cin >> n;
for(int i = 0; i<n; i++)
{
cin >> a[i];
b[i] = 1;
}
LIS(n);

for(int i = 0; i<n; i++)
{
if(result<b[i]) result = b[i];
}
cout << result <<endl;
return 0;
}


解法三:贪心加二分

此解法的思想是用一个一维数组来存储寻找子序列过程中值的变化情况:a中的当前的元素若大于或等于一维数组的最后一个有效元素,那么就把它加入到一维数组中作为数组的最后一个元素。如果小于,那么就在一维数组中找到第一个比它大的元素并替换掉。这样最后一维数组中的所有有效元素就构成了一个最长上升子序列。

另外,在找一维数组中第一个比a中当前元素大的元素时,可以采用二分查找的形式。要注意这里的二分查找不是普通的二分查找,而是要找上确界。

综合考虑,此解法的时间复杂度为O(n*log n)。

#include<iostream>
#define MAX 10000

using namespace std;

int a[MAX];
int b[MAX];

int binary_search(int n,int a)
{
int head = 1;
int tail = n;
int middle = 0;
while(head < tail)
{
middle = tail - (tail - head)/2;
if(b[middle-1] <= a && b[middle] >=a) return middle;
if(b[middle] < a)
{
head = middle;
}
else if(b[middle-1] > a )
{
tail = middle - 1;
}
}
return 1;
}

int LIS(int n)
{
int i = 0;
int max_len = 0;
int search_result = 0;
for(i = 0; i<n; i++)
{
if(b[max_len] <= a[i])
{
b[++max_len] = a[i];
}
else
{
b[binary_search(max_len, a[i])] = a[i];

abb6
}
}
return max_len;

}

int main()
{
int n = 0;
int i = 0;

cin >> n;
for(i = 0; i<n; i++)
{
cin >> a[i];
}

cout << "The longest increasing subsequence\'s length is: ";
cout <<LIS(n)<<endl;

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 动态规划