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 <bits/stdc++.h>
using namespace std;
int n;
int a[500005];
int dp[50005];
int main(int argc,char** argv){
	scanf("%d",&n);
	for(int i=0;i<n;i++) {
		scanf("%d",&a[i]);
	}
	int len = 1;
	dp[1] = a[0];
	for(int i=1;i<n;i++){
		if(a[i] > dp[len]){
			dp[++len] = a[i];
		}
		else{
			int ans = lower_bound(dp+1,dp+len,a[i])-dp;
			dp[ans] = a[i];
		}
	}
	printf("%d\n",len);
	return 0;
}
#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章