1. 程式人生 > >1134 最長遞增子序列(時間複雜度O(n*log(n))

1134 最長遞增子序列(時間複雜度O(n*log(n))

基準時間限制:1 秒 空間限制:131072 KB 分值: 0 難度:基礎題

Description

給出長度為N的陣列,找出這個陣列的最長遞增子序列。(遞增子序列是指,子序列的元素是遞增的)
例如:5 1 6 8 2 4 5 10,最長遞增子序列是1 2 4 5 10。

Input

第1行:1個數N,N為序列的長度(2 <= N <= 50000)
第2 - N + 1行:每行1個數,對應序列的元素(-10^9 <= S[i] <= 10^9)

Output

輸出最長遞增子序列的長度。

Input示例

8
5
1
6
8
2
4
5
10

Output示例

5

舉例:
陣列 d[] = 2 1 5 3 6 4 8 9 7 (其中最長上升子序列長度為 5)
陣列 B[] 最終的長度即為最長上升子序列的長度
d[1] = 2 –> B[1] = 2;
d[2] = 1 ( d[2] < B[1] ) –>B[1] = 1; B[] = 1
d[3] = 5 (d[3] > B[1]) –>B[2] = 5; B[] = 1 5
d[4] = 3 (d[4] < B[2]) –>B[2] = 3; B[] = 1 3
d[5] = 6 (d[5] > B[2]) –>B[3] = 6; B[] = 1 3 6
d[6] = 4 (d[6] < B[3]) –>B[3] = 4; B[] = 1 3 4
d[7] = 8 (d[7] > B[3]) –>B[4] = 8; B[] = 1 3 4 8
d[8] = 9 (d[8] > B[4]) –>B[5] = 9; B[] = 1 3 4 8 9
d[9] = 7 (d[9] < B[5]
&&d[9] < B[4]) –>B[4] = 7; B[] =1 3 4 7 9 所以長度為5;
注意::::陣列B 中存放的元素並不一定是最長上升子序列的元素

AC程式碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n;
int len;
int d[500005],B[500005];
//二分查詢
int search_bound(int i)
{
    int left,right,mid;
    left = 1,right = len;
    while(left <= right)
    {
        mid = (left + right)/2
; if(B[mid] == d[i]) return mid; else if(B[mid] > d[i]) right = mid-1; else left = mid+1; } return left; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&d[i]); B[1] = d[1]; //先把第一個元素放入 len = 1; for(int i=2;i<=n;i++) { if(d[i] > B[len]) //後一個比前一個大 B[++len] = d[i]; //直接放入陣列 else //否則二分查詢返回下界 { int pos = search_bound(i); B[pos] = d[i]; } } printf("%d\n",len); return 0; }

動態規劃程式碼:O(n^2)

//超時代嗎
#include <iostream>
#include <cstdio>
#define Max 1001

using namespace std;

int main()
{
    int i, j, n, maxx;
    // a[i]表示輸入第i個元素
    int a[Max];
    // d[i]表示以a[i]結尾的最長子序列長度
    int d[Max];

    scanf("%d",&n);
    for (i = 1; i <= n; i++)
        scanf("%d",&a[i]);

    maxx = 0;
    for (i = 1; i <= n; i++)
    {
        d[i] = 1;
        for (j = 1; j <= i - 1; j++)
        {
            if (a[j] < a[i] && d[i] < d[j] + 1)
            {
                d[i] = d[j] + 1;
            }
        }
        // 記錄最長子序列
        if (d[i] > maxx)
            maxx = d[i];
    }
    printf("%d\n",maxx);
    return 0;
}