zoukankan      html  css  js  c++  java
  • 最大递增子序列到理解

    const int MAXN = 1010;
    int n;
    int a[MAXN];
    int dp[MAXN];
    /*dp[i]表示以i结尾的子序列中LIS的长度。然后我用dp[j](0<=j<i)来表示在i之前的LIS的长度。然后我们可以看到,只有当a[i]>a[j]的时候,我们需要进行判断,是否将a[i]加入到dp[j]当中。为了保证我们每次加入都是得到一个最优的LIS,有两点需要注意:第一,每一次,a[i]都应当加入最大的那个dp[j],保证局部性质最优,也就是我们需要找到max(dp[j](0<=j<i));第二,每一次加入之后,我们都应当更新dp[j]的值,显然,dp[i]=dp[j]+1。
    如果写成递推公式,我们可以得到dp[i]=max(dp[j](0<=j<i))+(a[i]>a[j]?1:0)。
    于是我们就能够得到O(n^2)的动态规划方法的实现:*/
    int lis(){
        memset(dp,0,sizeof(dp));
        int max;
        for(int i=0;i<n;i++){
            max=0;
            for(int j=0;j<i;j++){
                if(a[i]>a[j]){
                    max=max(max,dp[j]);
                }
            }
            dp[i]=max+1;
        }
        max=0;
        for(int i=0;i<n;i++){
            max=max(max,dp[i]);        
        }
        return max;
    }
    
    /*
    O(Nlogn)的动态规划+二分方法
    
    在前一种方法中,我们花费了很多时间在寻找最大的dp[j]上。如果有办法让这个dp[j]变成一个递增的序列,我们就能使用二分来进行优化,从而使得复杂度下降为O(nlogn)了。
    幸运的是,这种方法确实是存在的。我们可以使用dp[i]来保存在前i个数中最大的那个数,很容易可以理解,这个dp[i]已经是单调不减的。接下来的处理其实有些贪心的思想,对于每一个a[i],我们都在dp数组中寻找比它大的第一个数的下标,不妨设为pos,然后用a[i]来更新dp[pos]。于是我们可以明白,len就应当是max(len, pos+1)。
    
    */
    /*
    这样做到好处是优化了时间复杂度,但是失去了最大递增子序列,也就是说,最后通过dp数组,我们只能计算出原数组到最大递增子序列到个数,但是不能得到这个序列
    */


  • 相关阅读:
    Markdown标签
    macbook使用
    git的使用
    HTTPS的原理
    javascript中的对象
    javascript中this的指向问题
    javascript中的闭包
    javaScript中的return、break和continue
    Promise对象
    ORACLE_11G归档空间满,由于数据库装完后使用的是默认空间是闪回区
  • 原文地址:https://www.cnblogs.com/superxuezhazha/p/5673473.html
Copyright © 2011-2022 走看看