您的位置:首页 > 其它

动态规划求 最长递增子序列

2013-12-14 20:04 302 查看
给出一段整数序列 , 要求出这个序列的最长递增子序列 。

方法一:

我们可以利用背包状态转移的思想 , 从后先前分析 , 我们先只考虑前 i-1 个元素中的最长递增子序列 , 当求前 i
个元素的最长递增序列时 , 我们只需要确定第 i 个元素可以放在前 i-1 个元素中哪些元素的后面 , 则 i
元素就能跟该元素构成一个新的序列。即:

k <= i-1 ;

xy[i] > xy[k] , 则 i 元素就能放在 k 元素的后面 ,
这样就构成了一个新的递增序列

代码:

int main()

{

    int
xy[100010] , n;

    int
dp[100010];

   
while(scanf("%lld" , &n) != EOF)

    {

    int i ,
j;

    for(i = 1; i
<= n; i++)

   
   
cin>>xy[i];

    //memset(dp
, 0 , sizeof(dp));

    dp[1] =
1;

    for(i = 2; i
<= n; i++)

    {

   
    dp[i] =
1;

   
    for(j = 1; j
< i; j++)//顺序查找

   
    {

   
   
    if(xy[j]
< xy[i] && dp[i]
< (dp[j]+1))

   
   
   
    dp[i] =
dp[j]+1;

   
    }

   
}//时间复杂度为:n*n

    int maxsum =
0;

    for(i = 1; i
<= n; i++)

   
    if(dp[i]
> maxsum)  maxsum = dp[i];

   
cout<<maxsum<<endl;

    }

    return
0;

}

方法二:(dp + 二分查找)

对于方法一 , 我们可以分析出其时间复杂度为:n*n , 这复杂度太高了 , 所以我们要在改善这个算法。

在方法一中我们是在用顺序查找来查找xy[i]在0~i-1中的位置 , 因此我们可以在这里下手 , 把顺序查找该为二分查找 ,
则时间复杂度变为了:n*lgn;

这个方法的原理:

首先我们知道 , 对于每一个长度(递增序列中的元素数量)的递增序列 , 我们只需要记录该序列的最后的一个元素就行了 ,
我们可以用一个数组 c 来储存 ,则c[1]就储存只有一个元素的递增序列中的最大那个数(也就是最后面那个数) , c[2]
就储存只有2个元素的递增序列中的最大那个数.........

因此我们就得到了一个有序的数组 c , 那么当我们确定 xy[i] 这个元素的最长递增序列时 , 我们只需要在 c
中找到最小的大于xy[i]的元素的位置 , 这个位置就是xy[i]的最长递增序列。

所以 , 我们需要长期来维护数组c

代码:

#include

using namespace std;

long long int xy[100100];

long long int c[100100];

long long int find(long long int n , long long int x)

{

    long long
int left = 1 , right = n ;

    long long
int mid;

    while(left
<= right)

    {

   
    mid =
(right+left)/2;

   
   if(c[mid] < x)  left =
mid + 1;  // 这里要注意 , 因为是要求大于 x 的元素的位子 ,
所以这里不能加等于

   
    else right =
mid - 1;

    }

    return
left;

}

int main()

{

    long long
int n;

   
while(scanf("%lld" , &n) != EOF)

    {

   
    long long
int i , j;

   
    for(i = 1; i
<= n; i++)

   
   
   
cin>>xy[i];

   
    c[0] =
-1;

   
    c[1] =
xy[1];

   
    long long
int len = 1;

   
    for(i = 2; i
<= n; i++)

   
    {

   
   
   j = find(len , xy[i]);

   
   
    c[j] =
xy[i];  //维护数组c

   
   
    if(j
> len)  len = j;

   
    }

   
   
cout<<len<<endl;

    }

    return
0;

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