日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(算法)最长递增子序列

發布時間:2023/12/9 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (算法)最长递增子序列 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題:

Given an array of N integer, find the length of the longest increasing subsequence.

For example, given [1,-5,4,5,10,-1,-5,7], the longest increasing subsequence is length 4.(1,4,510)

思路:

1、枚舉

枚舉數組所有的子序列,然后判斷它們是否為遞增子序列(回溯法)。

2、轉化

將數組排序,然后找出新數組和舊數組的最長公共子序列LCS。

(關于最長公共子序列,參考:http://www.cnblogs.com/AndyJee/p/4469196.html)

3、動態規劃

假設數組為A,len[i] 表示以第 i 個元素為結尾(即第i個元素為最大)的最長遞增子序列的長度;

求len[i],可以先求以前面i-1個元素結尾的最長遞增子序列,如果A[i]比前面A[0...i-1]中某個元素k小,那么就可以在相應的len[k]上加1,當然是最大的len[k];

詳見http://blog.csdn.net/kenby/article/details/6804720

4、優化

上述方法在求len[i]的時候, 要從a[1], ... a[i-1]中找出所有比 a[i] 小的元素,而a[1], ... a[i-1]是無序的,查找速度比較慢。

引出數組 f[k] 表示長度等于k的遞增子序列中最末尾的元素, 長度越長的序列,其末尾元素也越大,所以f[k]是遞增的。

實例 <1, 3, 4, 2, 7>

len[1] = 1, f[1] = a[1] = 1

len[2] = 2, f[2] = a[2] = 3

len[3] = 3, f[3] = a[3] = 4

len[4] = 2, f[2] = a[4] = 2 ( 更新了f[2] )

那么,如何求len[5] 呢?

f[1] = 1, f[2] = 2, f[3] = 4, a[5] = 7,

找出末尾元素比a[5]小,而且長度最長的遞增子序列,此例中,

f[3] = 4 表示長度等于3的子序列,其末尾元素為4,這個子序列的長度最長。

a[5]加上此序列形成的新序列長度為4, 然后更新f[4] = a[5] = 7,表示長度等于4的子序列,其末尾元素等于7

在上面的步驟中,找出末尾元素比a[i]小,而且長度最長的子序列,其實就是對于f[1], ...f[k], 從后往前找,第一個比a[i]小的元素就是長度最長的子序列。查找的時候可以用二分查找方法,故更快。

代碼:

1、動態規劃

#include <iostream> #include <vector> using namespace std;unsigned int LISS(const int array[], size_t length, vector<int> &result) {unsigned int liss[length];unsigned int pre[length];for(int i=0;i<length;++i){liss[i]=1;pre[i]=i;}int k=0;int max=1;for(int i=1;i<length;++i){for(int j=0;j<i;++j){if(array[j]<array[i] && liss[j]+1>liss[i]){liss[i]=liss[j]+1;pre[i]=j;if(max<liss[i]){max=liss[i];k=i;}}}}// i = max - 1;while(pre[k]!=k){ // result[i--] = array[k];result.push_back(array[k]);k=pre[k];}//result[i] = array[k];result.push_back(array[k]);return max; }int main() {int A[]={1,-5,4,5,10,-1,-5,7};int len=sizeof(A)/sizeof(A[0]);vector<int> result;cout << LISS(A,len,result) << endl;for(int i=0;i<result.size();i++)cout<<result[i]<<' ';cout<<endl; }

2、優化

#include <iostream> #include <vector> using namespace std;unsigned int LISS(const int array[], size_t length, vector<int> &result) {unsigned int liss[length];unsigned int pre[length];unsigned int f[length];for(int i=0;i<length;++i){liss[i]=1;pre[i]=i;f[i]=0;}int k=0;int max=1;f[max]=0;for(int i=1;i<length;++i){for(int j=max;j>=1;--j){if(array[f[j]]<array[i]){liss[i]=j+1;pre[i]=f[j];if(f[liss[i]]!=0){int old=array[f[liss[i]]];if(array[i]<old)f[liss[i]]=i;}elsef[liss[i]]=i;if(max<liss[i]){max=liss[i];k=i;}break;}}}// i = max - 1;while(pre[k]!=k){ // result[i--] = array[k];result.push_back(array[k]);k=pre[k];}//result[i] = array[k];result.push_back(array[k]);return max; }int main() {int A[]={1,3,4,2,7};int len=sizeof(A)/sizeof(A[0]);vector<int> result;cout << LISS(A,len,result) << endl;for(int i=0;i<result.size();i++)cout<<result[i]<<' ';cout<<endl; }

在線測試OJ:

http://www.nowcoder.com/questionTerminal/585d46a1447b4064b749f08c2ab9ce66

AC代碼:

class AscentSequence { public:int findLongest(vector<int> A, int n) {vector<int> dp(n);vector<int> f(n);dp[0]=1;f[0]=A[0];int left,right,mid;int count=0;int lmax=1;for(int i=1;i<n;i++){left=0;right=count;while(left<=right){mid=left+((right-left)>>1);if(A[i]>=f[mid])left=mid+1;elseright=mid-1;}f[left]=A[i];if(left>count)count=left;dp[i]=left+1;if(lmax<dp[i])lmax=dp[i];}return lmax; } };

?

class AscentSequence { public:int findLongest(vector<int> A, int n) {int len=A.size();if(len<=1)return len;vector<int> mLen(n,1);int lMax=1;for(int i=1;i<n;i++){for(int j=0;j<i;j++){if(A[i]>A[j] && mLen[j]+1>mLen[i])mLen[i]=mLen[j]+1;if(mLen[i]>lMax)lMax=mLen[i];}}return lMax;} };

轉載于:https://www.cnblogs.com/AndyJee/p/4703332.html

總結

以上是生活随笔為你收集整理的(算法)最长递增子序列的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。