首先引出乙個例子
問題 :
給你乙個長度為 6 的陣列 , 陣列元素為 , 則其最長單調遞增子串行為 , 並且長度為 5 。
分析 :
題目所要找的遞增子串行 , 想想有什麼特點呢 ? 是不是會發現 所有的遞增序列 ,前乙個數一定小於後乙個數 ,並且如果給所有從小到大的數標號 , 會得到一串遞增的數 。
既然是借助動態規劃分析問題 , 那麼當前的產生的結果 , 僅僅只與前一次狀態有關 ,一直推的話 , 那麼是不是就很自然地想到我最最簡單的問題就是當陣列中的元素只有乙個的時候 , 並且我還要在開乙個陣列 , 記錄所有元素的位置 。
#include #include #include #include using namespace std ;現在如果要輸出這個遞增的序列 , 要怎麼做呢?#define min(a,b) a>b?b:a
#define max(a,b) a>b?a:b
int main ( ) ;
int pt[10] ;
for ( int i = 0 ; i < 7 ; i++ )
pt[i] = 1 ;
for ( int i = 1 ; i < 7 ; i++ )
}int maxn = 0 ;
for ( int i = 0 ; i < 7 ; i++ )
maxn = max ( maxn , pt[i] ) ;
cout << maxn << endl ;
return 0 ;
}
int maxn = 0 , t ;順便給出 pt[ ] 陣列中所存的資料for ( int i = 0 ; i < 7 ; i++ )
if ( maxn < dp[i] )
for ( int i = 6 ; i >= 0 ; i-- ) }}
}
優化 :
上述方法還是很好理解的 , 但是複雜度確實 n^2 , 現在有一種優化手段 , 可以將複雜度優化為 降為 n * log n ,這種方法的核心思想 , 在二分下寫 , 維護乙個當前的最優的遞增序列 , 找到恰好大於它的更新 。
舉個小例子
比如陣列 a[ ] = , 現將 a [ 1 ] 放入放入新陣列 b [ ] 中 ,則 b[ 0 ] = 1 , 在 取出 a[ 1 ] = 3 , 將其放入 b 陣列中 , 因為 3 恰好比 b[ 0 ] 大 , 所以 將 b[ 1 ] = 3 , 在拿出 a[ 2 ] , 將 2 在陣列 b 中二分 , 尋找位置 , 因為 2 恰好位於 1 和 3 之間 , 所以此時要用 2 去替換 3 的位置 ,即在 b 陣列中得到乙個新的有序的序列 , 但此序列並不是最長遞增的子串行 ,它僅僅只是儲存對應長度lis 的最小末尾 。
#include #include #include #include using namespace std ;#define min(a,b) a>b?b:a
#define max(a,b) a>b?a:b
int arr[7] = ;
int dp[10] ;
int fun ( int key , int l , int r )
while ( l <= r )
// printf ( "\n\n l = %d r = %d \n" , l , r ) ;
return l ;
}int main ( )
int cnt = 0 ;
for ( int i = 0 ; i < 4 ; i++ )
if ( dp[i] > 0 ) cnt++ ;
cout << cnt << '\n' ;
return 0 ;
}
dp 最長單調遞增子串行LIS
解題關鍵 如果將子串行按照長度由短到長排列,將他們的最大元素放在一起,形成新序列 b left ldots ldots right 則序列 b 滿足 ldots ldots 這個關係比較容易說明,假設 表示序列a中長度為 x 的遞增序列中的第 y 個元素,顯然,如果在序列 b 中存在元素 且 m n...
最長遞增子串行 LIS
對於這個問題,最直觀的dp方法是cnt i 表示以height i 結束的最長遞增子串行的元素的個數,遞迴方程是cnt i max for max i 0 i求出整個數列的最長遞增子串行的長度 if b i max max b i cout return 0 顯然,這種方法的時間複雜度仍為o n 2...
最長遞增子串行 LIS
給定乙個長度為n的陣列,找出乙個最長的單調自增子序列 不一定連續,但是順序不能亂 例如 給定乙個長度為6的陣列a,則其最長的單調遞增子串行為,長度為4.這個問題可以轉換為最長公共子串行問題。如例子中的陣列a,則我們排序該陣列得到陣列a 然後找出陣列a和a 的最長公共子串行即可。顯然這裡最長公共子串行...