傳聞:索尼將本週公佈三個PlayStation重大訊息
阿新 • • 發佈:2022-03-28
方法一:動態規劃
特點:用動規方法求解可以得到LIS的路徑,時間複雜度為n^2
狀態:dp[ i ] 為以 a[ i ] 為結尾的最長子序列大小,初始值都為 1
狀態轉移方程:dp[ i ] = max( dp[ j ] ) + 1 (限制條件:j < i && a[ j ] < a[ i ] )
程式碼實現:
for ( int i = 1 ; i <= n ; i++ ) { dp [ i ] = 1 ; for ( int j = 1 ; j < i ; j++ ) {if ( a [ j ] < a [ i ] ) { dp [ i ] = max ( dp [ i ] , dp [ j ] + 1 ) ; } } }
方法二:貪心/二分
特點:無法得到LIS路徑,時間複雜度為nlogn
狀態:g[ i ] 陣列表示長度為 i 的所有上升子序列結尾的最大值
維護:遍歷陣列a,對於元素 a[ i ] ,如果有 g[ len ] < a[ i ] ,則 g[ ++len ] = a[ i ] ,如果有 g[ len ] >= a[ i ] ,那麼就要在g陣列中找到第一個比 a[ i ] 大的數並替換成 a[ i ] (貪心的性質,如果結尾越小越有利於後續數字的插入)。查詢的過程用二分查詢。
程式碼實現:
int len = 0 ; g [ ++len ] = a [ 1 ] ; for ( int i = 2 ; i <= n ; i++ ) { if ( a [ i ] > g [ len ] ) g [ ++len ] = a [ i ] ; else { int pos = lower_bound ( g + 1 , g + len + 1, a[ i ] ) - g ; g [ pos ] = a [ i ] ; } }