The longest increasing subsequence two approaches
Here to give a example, you can complete understanding to do it. HRBUST-1835
Complexity \ (O (N ^ 2) \) approach
Dynamic programming approach
Has a length N of the array {a0, a1, a2, a3, ..., an-1}, we assume that the array is incremented to the longest sequence aj ending subsequence length dp [j], then dp [j ] = max (dp [i] +1, i <j and a [i] <a [j]). We need to traverse all positions before i j, find the greatest value of this.
For more details see the other code.
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e3;
int a[N];
int dp[N];
int main()
{
int n;
while(scanf("%d", &n)!=EOF)
{
for(int i=0; i<n; i++)
{
scanf("%d", &a[i]);
dp[i]=1; //每个需要初始化为1,因为每一个都可以自己成为一个最短的子序列
}
int ans=1;//答案最小是1
for(int i=1; i<n; i++)
{
for(int j=0; j<i; j++)
{
if(a[j]<a[i] && dp[j]+1 > dp[i]) //这里需要满足两个条件,前面的数值小于a[i],并且加上这个序列后能够使得dp[i]增加。
{
dp[i]=dp[j]+1;
}
}
ans=max(ans, dp[i]);//这里求出dp中的最大值。
}
printf("%d\n", ans);
}
return 0;
}
Complexity \ (O (N * lgN) \) algorithm
For an increasing sequence of length n, we want this number as small as possible at the end of the sequence, because only then when we want to add a digital back, this figure can be relatively small.
Such a process is.
Suppose there is a sequence d [1..9] = {2,1, 5, 3, 6,4, 8, 9, 7}, it can be seen LIS length of 5. The following step by step, try to find it.
We define a sequence of B, and so i = 1 to 9 individually examine this sequence. In addition, we use a variable to record Len now up to count the number of
First, the D [1] in an orderly manner into B, so that B [1] = 2, a number that is a time when only 2, the minimum length of the end of the LIS is 2 to 1. Then Len = 1
Then, d [2] in an orderly manner into B, so that B [1] = 1, that is the minimum length of the end of the LIS 1 is 1, d [1] = 2 has been useless, it is readily appreciated it. Then Len = 1
Then, d [3] = 5, d [3]> B [1], so it is B [1 + 1] = B [2] = d [3] = 5, that is the minimum length of the end of the LIS 2 5, it is easy to understand it. This time B [1..2] = 1, 5, Len = 2
Again, d [4] = 3, it is just applied between 1,5, is placed at position 1 clearly inappropriate, because 1 is less than 3, the length of the end of the LIS 1 should be a minimum, it is easy to deduce the length 2 to the end of the LIS is minimum 3, 5 can thus eliminate this time B [1..2] = 1, 3, Len = 2
Continue, d [5] = 6, 3 behind it, because the B [2] = 3, 3 and 6 in the back, so can easily deduce B [3] = 6, time B [1..3] = 1, 3, 6, or easy to understand, right? Len = 3 oh.
Sixth, d [6] = 4, you see it between 3 and 6, so we can replace 6, to obtain B [3] = 4. B [1..3] = 1, 3, 4, Len continues equal to 3
7th, d [7] = 8, it is large, larger than 4, ah. Then B [4] = 8. Len turned into a 4
8th, d [8] = 9, to obtain B [5] = 9, ah. Len continues to increase, up to 5.
Finally a, d [9] = 7, in which B [. 3] = 4 and between B [4] = 8, so we know the latest B [4] = 7, B [1..5] = 1 , 3, 4, 7, 9, Len = 5.
So we know the length of the LIS is 5.
This last number of array B is stored in the corresponding end of the LIS minimum length, the length of the sequence is the same, the minimum value of the end.
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=107;
int a[maxn];
int main()
{
int n;
while(scanf("%d", &n)!=EOF)
{
for(int i=1; i<=n; i++)
{
scanf("%d", &a[i]);
}
int len=1, pos;
for(int i=2; i<=n; i++)//这里我没有用两个数组,因为使用原来的数组也可以
{
pos=lower_bound(a+1, a+len+1, a[i])-a; //这里使用了lower_bound函数来进行查找第一个小于等于a[i]的数字
if(pos>len)//如果位置大于了len长度的时候需要len++
len++;
a[pos]=a[i];
}
printf("%d\n", len);
}
return 0;
}