基準時間限制: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;
}