zoukankan      html  css  js  c++  java
  • LIC

    问题描述:

    一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, ..., aN),我们可以得到一些上升的子序列(ai1, ai2, ..., aiK),这里1 <= i1 < i2 < ... < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).

    你的任务,就是对于给定的序列,求出最长上升子序列的长度。

    解法1:

    时间复杂度O(n^2);

     1 /*
     2 dp[i]:以a[i]结尾的字符串长度;
     3 有两种可能性;
     4 1.只包含a【i】
     5 2.附加到j<i&&a[j]<a[i],那么dp[i]=max(dp[j]+1,dp[i])
     6 */
     7 
     8 #include <iostream>
     9 #include <cstdio>
    10 #include <cstring>
    11 using namespace std;
    12 
    13 const int MAXN=100000;
    14 const int INF=1<<30;
    15 
    16 int a[MAXN];
    17 int dp[MAXN];  //代表以a【i】为结尾的序列的长度。
    18 
    19 int main(){
    20     int n;  //代表序列的个数
    21     while(scanf("%d",&n)!=EOF){
    22         for(int i=0;i<n;i++)
    23             scanf("%d",&a[i]);
    24 
    25         memset(dp,0,sizeof(dp));
    26 
    27         int ans=-INF;
    28         for(int i=0;i<n;i++){
    29             dp[i]=1;  //这是只有a[i];
    30             for(int j=0;j<i;j++)
    31                 if(a[j]<=a[i])
    32                     dp[i]=max(dp[j]+1,dp[i]);
    33             ans=max(ans,dp[i]);
    34 
    35         }
    36         cout<<ans<<endl;
    37     }
    38 }

    方法二:

    时间复杂度:O(nlgn)

    /*
    dp[i]:长度为i+1的上升子序列中末尾的最小值:
    很明显长度i的子序列,其dp【i]越小,其在后面越占优势,而如何来更新dp【i】的值呢
    上面一个算法,在查找的浪费了大量的时间,
    这儿的dp数组的值明显是单调递增的。可以用二分搜索来查找,就可以把整个算法的时间复杂度,降低为O(nlgn);
    */
    
    int bSearch(int num, int k)  
    {  
        int low=1, high=k;  
        while(low<=high)  
        {  
            int mid=(low+high)/2;  
            if(num>=dp[mid])  
                low=mid+1;  
            else   
                high=mid-1;  
        }  
        return low;  
    }  
     
    int LIS()
    {
        int low = 1, high = n;
        int k = 1;
        dp[1] = a[1];
        for(int i=2; i<=n; ++i)
        {
            if(a[i]>dp[k])
                dp[++k] = a[i];
            else
            {
                int pos = bSearch(a[i], k);
                dp[pos] = a[i];
            }
        }
        return k;
    }
    
    void solve(){
        fill(dp,dp+n,INF);
        for(int i=0;i<n;i++)
            *lower_bound(dp,dp+n,a[i])=a[i];   //这是找到dp[i]>=a[i]的最小只真
        printf("%d
    ",lower_bound(dp,dp+n,INF)-dp);
    }
    自己选的路,跪着也要把它走完------ACM坑
  • 相关阅读:
    Java并发编程:CountDownLatch、CyclicBarrier和Semaphore (总结)
    Java线程面试题 Top 50 (个人总结)(转)
    rabbitMQ windows 安装 入门(转)
    Java并发编程:volatile关键字解析(学习总结-海子)
    关于Sychronized和volatile自己总结的一点点理解(草稿)
    FWORK-数据存储篇 -- 范式与反模式 (学习和理解)
    Synchronized的原理及自旋锁,偏向锁,轻量级锁,重量级锁的区别(摘抄和理解)
    vcfc之zk+postsql+keystore(cassandra)框架分析
    CAP理论-解析
    java多线程通信 例子
  • 原文地址:https://www.cnblogs.com/IKnowYou0/p/6591200.html
Copyright © 2011-2022 走看看