演算法:最長上升下降子序列,演算法最長上升序列

來源:互聯網
上載者:User

演算法:最長上升下降子序列,演算法最長上升序列
問題

給定n個數,從中拿走x(x>=0)個數,使剩下的數最有下列性質。
A1 < A2 < A3 <…At > At+1 >At+2 > … > As
問最少要抽掉幾個數,此數列才會具有以上性質。


圖解

代碼

#include "stdafx.h"const int MAX=105;int down[MAX],up[MAX];int h[MAX],n;void get_up(){int i,tmp,j;for(i=0;i<n;i++){tmp=1;for(j=i-1;j>=0;j--){if(h[i]>h[j]&&up[j]+1>tmp)tmp=up[j]+1;}up[i]=tmp;}}void get_down(){int i,j,tmp;for(i=n-1;i>=0;i--){tmp=1;for(j=i+1;j<n;j++){if(h[i]>h[j]&&down[j]+1>tmp)tmp=down[j]+1;}down[i]=tmp;}}int main(){int i,max;while(scanf("%d",&n)!=EOF){for(i=0;i<n;i++)scanf("%d",&h[i]);get_up();get_down();max=0;for(i=0;i<n;i++){if(up[i]+down[i]-1>max)max=up[i]+down[i]-1;}printf("%d\n",n-max);}return 0;}




最長上升子序列nlogn的演算法怎寫

a:array[0..100001]of int64;//為數組
d:array[0..100001]of int64;//隊列
now:longint;
function search(x:longint):longint;//二分尋找與X最接近的值的位置
var l,r,mid:longint;
begin
l:=1;r:=top;
while l<>r do
begin
mid:=(l+r)div 2;
if d[mid]>x then r:=mid else l:=mid+1;
end;
exit(l);
end;
begin
fillchar(d,sizeof(d),0);//初始化
top:=1;//top 為已產生隊列中的個數
now:=1;
d[1]:=a[1];
for i:=2 to n do
begin
if a[i]<=d[1] then j:=1;
if a[i]>=d[top] then j:=top+1;
if (a[i]>d[1])and(a[i]<d[top]) then
j:=search(a[i]);
now:=j;
if j>top then begin inc(top); d[top]:=a[i];end;
if a[i]<d[j] then d[j]:=a[i];
if now>max then max:=now;//now 為最大值
end;
//具體思想為:
因為D是單調的,所以我可以對數組中的數進行下面處理!
我要產生一個最長上升子序列,將其放在數組D中,從1至N每枚舉每個數,
對其進行如下操作
1:若他比D[TOP]小,則說明其是當前最小的,j:=1;
2:若他比D[TOP]大,則就排入佇列中去,j:=top+1;
3:若他既比D[top]小,又比D[1]大,則二分尋找他在D隊列中的置,j:=search(a[i]);
這就是具體思想!
還有什麼不懂得嗎??
 
最長上升序列動態規劃方程的解釋

有兩種演算法複雜度為O(n*logn)和O(n^2)

O(n^2)演算法分析如下: (a[1]...a[n] 存的都是輸入的數)
1、對於a[n]來說,由於它是最後一個數,所以當從a[n]開始尋找時,只存在長度為1的不下降子序列;
2、若從a[n-1]開始尋找,則存在下面的兩種可能性:
(1)若a[n-1] < a[n] 則存在長度為2的不下降子序列 a[n-1],a[n].
(2)若a[n-1] > a[n] 則存在長度為1的不下降子序列 a[n-1]或者a[n]。
3、一般若從a[t]開始,此時最長不下降子序列應該是按下列方法求出的:
在a[t+1],a[t+2],...a[n]中,找出一個比a[t]大的且最長的不下降子序列,作為它的後繼。
4、為演算法上的需要,定義一個數組:
d:array [1..n,1..3] of integer;
d[t,1]表示a[t]
d[t,2]表示從i位置到達n的最長不下降子序列的長度
d[t,3]表示從i位置開始最長不下降子序列的下一個位置
最長不下降子序列的O(n*logn)演算法分析如下:
先回顧經典的O(n^2)的動態規划算法,設A[t]表示序列中的第t個數,F[t]表示從1到t這一段中以t結尾的最長上升子序列的長度,初始時設F[t] = 0(t = 1, 2, ..., len(A))。則有動態規劃方程:F[t] = max{1, F[j] + 1} (j = 1, 2, ..., t - 1, 且A[j] < A[t])。
現在,我們仔細考慮計算F[t]時的情況。假設有兩個元素A[x]和A[y],滿足
(1)x < y < t (2)A[x] < A[y] < A[t] (3)F[x] = F[y]
此時,選擇F[x]和選擇F[y]都可以得到同樣的F[t]值,那麼,在最長上升子序列的這個位置中,應該選擇A[x]還是應該選擇A[y]呢?
很明顯,選擇A[x]比選擇A[y]要好。因為由於條件(2),在A[x+1] ... A[t-1]這一段中,如果存在A[z],A[x] < A[z] < a[y],則與選擇A[y]相比,將會得到更長的上升子序列。
再根據條件(3),我們會得到一個啟示:根據F[]的值進行分類。對於F[]的每一個取值k,我們只需要保留滿足F[t] = k的所有A[t]中的最小值。設D[k]記錄這個值,即D[k] = min{A[t]} (F[t] = k)。
注意到D[]的兩個特點:
(1) D[k]的值是在整個計算過程中是單調不上升的。
(2) D[]的值是有序的,即D[1] < D[2] < D[3] < ... < D[n]。
利用D[],我們可以得到另外一種計算最長上升子序列長度的方法。設當前已經求出的最長上升子序列長度為len。先判斷A[t]與D[len]。若A [t] > D[len],則將A[t]接在D[len]後將得到一個更長的上升子序列,len = len + 1, D[len] = A[t];否則,在D[1]..D[len]中,找到最大的j,滿足D[j] < A[t]。令k = j + 1,則有D[j] < A[t] <= D[k],將A[t]接在D[j]後將得到一個更長的上升子序列,同時更新D[k] = A[t]。最後,len即為所要求的最長上升子序列的長度。
在上述演算法中,若使用樸素的順序尋找在D[1]..D[len]尋找,由......餘下全文>>
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.