最長上公升子串行問題的幾種解法

2021-08-31 08:28:43 字數 2266 閱讀 9144

拿poj 2533來說。

sample input 7

1 7 3 5 9 4 8

sample output 4

從輸入的序列中找出最長的上公升子串行(lis)。

這題一看,是一道典型的dp問題(就是動態規劃),可以用dfs,深度優先遍歷來解,如下**:

#include

#include

using namespace std;

int n;

int* a;

stacks;

int count=0;

int best=0;

void dfs(int i)

if(s.empty()||a[i]>s.top())

if(s.size()+n-i-1>best) dfs(i+1);

} int main()

dfs(0);

cout<}

return 0;

}其實為了簡化**以及演算法效率,我們可以用資料組來代替遞迴。。。下面我就給出lis的dp的資料組形式的解法:

(懶得寫了,就拿個別人的**來展示吧)

#include

#define size 1001

using namespace std;

int main()

max = 0;

for (i = 1; i <= n; i++)

}/* 記錄最長子序列 */

if (d[i] > max) max = d[i];

}cout << max << endl;

}//system("pause");

return 0;

}(作者的解釋:)令a[i]表示輸入第i個元素,d[i]表示從a[1]到a[i]中以a[i]結尾的最長子序列長度。對於任意的0 <  j <= i-1,如果a(j) < a(i),則a(i)可以接在a(j)後面形成乙個以a(i)結尾的新的最長上公升子串行。對於所有的 0 <  j <= i-1,我們需要找出其中的最大值。

dp狀態轉移方程:

d[i] = max (j = 1, 2, 3, ..., i-1 且 a[j] < a[i])

解釋一下這個方程,i, j在範圍內:

如果 a[j] < a[i] ,則d[i] = d[j] + 1

如果 a[j] >= a[i] ,則d[i] = 1

其實上面的方法的複雜度都達到了o(n^2)的數量級,有沒有更好的解法呢?

有,用棧。

這個解法不是我想的,從網上學來的,這裡面與大家分享一下。這個演算法的複雜度只有o(nlogn),在有大量資料的情況下,這演算法效率極高。。。

(摘錄原作者的話)

這個演算法其實已經不是dp了,有點像貪心。至於複雜度降低其實是因為這個演算法裡面用到了二分搜尋。本來有n個數要處理是o(n),每次計算要查詢n次還是o(n),一共就是o(n^2);現在搜尋換成了o(logn)的二分搜尋,總的複雜度就變為o(nlogn)了。

這個演算法的具體操作如下(by ryanwang):

開乙個棧,每次取棧頂元素top和讀到的元素temp做比較,如果temp > top 則將temp入棧;如果temp < top則二分查詢棧中的比temp大的第1個數,並用temp替換它。 最長序列長度即為棧的大小top。

這也是很好理解的,對於x和y,如果x < y且stack[y] < stack[x],用stack[x]替換stack[y],此時的最長序列長度沒有改變但序列q的''潛力''增大了。

舉例:原序列為1,5,8,3,6,7

棧為1,5,8,此時讀到3,用3替換5,得到1,3,8; 再讀6,用6替換8,得到1,3,6;再讀7,得到最終棧為1,3,6,7。最長遞增子串行為長度4。

我想,當出現1,5,8,2這種情況時,棧內最後的數是1,2,8不是正確的序列啊?難道錯了?

分析一下,我們可以看出,雖然有些時候這樣得不到正確的序列了,但最後算出來的個數是沒錯的,為什麼呢?

想想,當temp>top時,總個數直接加1,這肯定沒錯;但當temp

用該演算法完成poj2533的具體**如下:

#include 

#define size 1001

using namespace std;

int main(

)else

else

}/* 用temp替換 */

stack[low]

= temp;}}

/* 最長序列數就是棧的大小 */

cout

<< top << endl;

} return0;

}

最長上公升子串行問題的幾種解法

拿poj 2533來說。sample input 7 1 7 3 5 9 4 8 sample output 從輸入的序列中找出最長的上公升子串行 lis 這題一看,是一道典型的dp問題 就是動態規劃 可以用dfs,深度優先遍歷來解,如下 include include using namespac...

最長上公升子串行問題的幾種解法

拿poj 2533來說。sample input 7 1 7 3 5 9 4 8 sample output 從輸入的序列中找出最長的上公升子串行 lis 這題一看,是一道典型的dp問題 就是動態規劃 可以用dfs,深度優先遍歷來解,如下 include include using namespac...

最長上公升子串行(Python and C 解法)

給定乙個無序的整數陣列,找到其中最長上公升子串行的長度。示例 輸入 10,9,2,5,3,7,101,18 輸出 4 解釋 最長的上公升子串行是 2,3,7,101 它的長度是 4。說明 子串行不同於子串,可以不連續。採用動態規劃。定義狀態 dp i 表示以 nums i 這個數為結尾的最長遞增子串...