最长上升子序列(Longest increasing subsequence)
?
問題描述
????????對于一串數A={a1a2a3…an},它的子序列為S={s1s2s3…sn},滿足{s1<s2<s3<…<sm}。求A的最長子序列的長度。
動態規劃法
算法描述:
????????設數串的長度為n,L[i]為以第i個數為末尾的最長上升子序列的長度,a[i]為數串的第i個數。
????????L[i]的計算方法為:從前i-1個數中找出滿足a[j]<a[i](1<=j<i)條件的最大的L[j],L[i]等于L[j]+1。
動態規劃表達式:
代碼實現:
上述算法的時間復雜度為O(n2)。
改進算法:
????????在從前i-1個數中找出滿足a[j]<a[i](1<=j<i)條件的最大的L[j]的時間復雜度為O(n),這里采用二分查找的方法對它進行優化,使其復雜度降為O(nlogn)。
????????增設一個m[]數組,m[x]存放長度為x的最長上升子序列的最小末尾數。例:m[3] = 17表示長度為3的最長上升子序列的最小末尾數為17。
????????由于子序列是上升的,所以m數組中的元素有一個性質,當x<y時,m[x]<m[y],利用這個性質來使用二分查找。
設m數組所存儲的最長上升子序列的長度為k,當前計算的數為第i個
如果a[i]>m[k],則m[++k]=a[i];
否則在m[1~k]內二分查找小于(等于)a[i]的最大值的位置p,m[p]=a[i]。
代碼實現:
int BSearch(int a[], int n, int t) {int low = 1;int high = n;while (low <= high){int mid = (low + high) / 2;if (t == a[mid]){return mid;}else if (t > a[mid]){low = mid + 1;}else{high = mid - 1;}}return low; }int LIS_BSearch(int a[], int m[], int n) {int maxlen = 1;?? ??? ?//最長上升子序列的長度m[maxlen] = a[1];int i;for (i = 2; i <= n; i++){if (a[i] > m[maxlen]){m[++maxlen] = a[i];}else{//返回小于a[i]的最大值的位置pint p = BSearch(m, maxlen, a[i]);m[p] = a[i];}}return maxlen; }改進后的算法時間復雜度為O(nlogn)。
?
總結
以上是生活随笔為你收集整理的最长上升子序列(Longest increasing subsequence)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: I NEED A OFFER!
- 下一篇: Choose the best rout