最長上公升子串行問題的兩個解題方法

2021-10-18 16:08:22 字數 1892 閱讀 8535

給定乙個長度為n的數列,求數值嚴格單調遞增的子串行的長度最長是多少。

輸入格式

第一行包含整數n。

第二行包含n個整數,表示完整序列。

輸出格式

輸出乙個整數,表示最大長度。

資料範圍

1 ≤ n ≤ 1000,

−1 09

10^9

109 ≤ 數列中的數 ≤ 109

10^9

109輸入樣例:

7

3 1 2 1 8 5 6

輸出樣例:

演算法1

(動態規劃) o(n

2n^2

n2)狀態表示:dp[i]表示從第乙個數字開始算,以a[i]結尾的最大的上公升序列。(以a[i]結尾的所有上公升序列中屬性為最大值的那乙個)

狀態計算(集合劃分):j∈(0,1,2, … , i - 1) , 在a[i] > a[j]時,

dp[i] = max(dp[i] , dp[i] + 1)。

有乙個邊界,若前面沒有比i小的,dp[i]為1(自己為結尾)。

最後在找dp[i]的最大值。

時間複雜度

o(n

2n^2

n2) 狀態數(n) * 轉移數(n)

c++ **

#include

using

namespace std;

const

int n =

1010

;int a[n]

, dp[n]

;int

main()

ans =

max(ans, dp[i]);

} cout << ans << endl;

return0;

}

演算法2

(動態規劃 + 二分) o(nlo

gn

nlog_n

nlogn​

)狀態表示:f[i]表示長度為 i 的最長上公升子串行,末尾最小的數字。(長度為i的最長上公升子串行所有結尾中,結尾最小min的) 即長度為i的子串行末尾最小元素是什麼。

狀態計算:維護乙個陣列,使其為遞增序列,以 ans-1 為下標的數為該陣列的最大數,每次新輸入的數都放到該陣列中比該數大的第乙個數的位置,如果陣列中沒有比該數大的數則放在最後面。

f[i]一定以乙個單調遞增的陣列,所以可以用二分法來找第乙個大於或等於 x 的數字。

時間複雜度

o(n lo

gn

nlog_n

nlogn​

) 狀態數(n) * 轉移數(log

nlogn

logn

)c++ **

#include

#include

using

namespace std;

const

int n =

1010

;int f[n]

;int

main()

else

if(x > f[ans-1]

) f[ans++

]= x;

} cout << ans << endl;

}

優化 最長上公升子串行 最長上公升子串行解題報告

給定乙個長度為n的數列 w n 求數值嚴格單調遞增的子串行的長度最長是多少。輸入格式 第一行包含整數n。第二行包含n個整數,表示完整序列。輸出格式 輸出乙個整數,表示最大長度。資料範圍 1 n 1000,1e9 數列中的數 1e9 輸入樣例 7 3 1 2 1 8 5 6 輸出樣例 4 includ...

最長上公升子串行問題

網上一大堆,說說思路吧,以4 2 6 3 1 5為例 逐個讀入數字,4 此時可能的佇列長度為1,最大值為4 4 2 由於2 4,此時佇列長度為1,最大值為2 4 2 6 6 2,佇列有2個,乙個長度為1,最大為2,乙個長度為2,最大為6 4 2 6 3 3 6,3 2,佇列有2個,乙個長度為1,最大...

最長上公升子串行問題

題型 poj 1631 問題描述 給出乙個陣列,求最長上公升子串行的長度。方法一 時間複雜度n 1000 思路 邊輸入邊處理,每次往陣列裡存,就替換這個數 就是所謂的二分法 include include include include using namespace std int a 40000...