演算法分析 單調遞增子串行

2021-10-23 03:51:39 字數 1983 閱讀 6561

設計乙個演算法,找出由n個數組成的序列的最長單調遞增子串行並對演算法進行分析。要求時間複雜度分別為o(nlogn)和o(n^2).

對陣列進行遍歷,我們設定乙個計數器來統計遞增序列的長度並初始化為1(最短的遞增序列是乙個單獨的陣列,因此初始化為1)每次如果後乙個數》前乙個數,則計數器+1,否則將計數器置為1。當每次碰到遞減的數時,更新最大計數器,然後再將計數器置為1.

#include

#include

#include

using

namespace std;

intmain()

count =1;

max_count =0;

for(

int i =

1;i < n;i++

)else

count +=1

;}cout

0;

方法1我們只需要遍歷我們的陣列,找到乙個遞增序列就+1即可,這是一次遍歷,所以時間複雜度為o(n)

利用動態規劃解決問題。我們發現其實截止到陣列arr[i]的最長單調子串行長度其實就是之前的元素的最大子串行長度.我們不斷更新當前元素之前的最大單調子串行長度,只是為了更新我們當前元素的最大長度。

所以我們設定b[0:n-1]來儲存陣列中a[i]的最大單調遞增子串行長度,我們要做的就是不斷更新b中的元素。

#include

using

namespace std;

const

int maxn=

100010

;int a[maxn]

=,b[maxn]=;

intlis

(int a,

int n)

b[i]

=k+1;}

int res=0;

for(

int i=

0;i)return res;

}int

main()

cout<<

printf

("%d"

,lis

(a,n)

)return0;

}

我們每次在找a[i]的最大遞增序列時都會遍歷之前的所有b[0:i],因此演算法時間複雜度為o(n^2)

方法3是一種最為簡便的方法,擴充套件序列。

我們發現在遍歷到i的時候,前面所有b陣列中的元素我們都需要遍歷,因此這造成了很大程度的時間浪費。我們可以重新定義乙個陣列b,陣列b[k]中儲存的是長度為k的遞增序列中最小元素末尾。所以當我們遍歷到a[i]時需要比較:

·a[i]>=b[k],b[k++] = a[i]

·a[i]#include

using

namespace std;

const

int maxnum =

100010

;int a[maxnum]=;

int b[maxnum]=;

intbinarysearch

(int x,

int i ,

int j)

return l;

}int

lis(

int a,

int n)

return k;

}int

main()

{int n;

cin>>n;

for(

int i =

0;i < n;i++

) cin>>a[i]

; cout<<

lis(a,n)

0;b[k]為長度為k的遞增序列的末尾最小元素,當碰到乙個小於當前a[i]的數字,我們會進入b中進行位置搜尋,搜到了位置j後我們會立刻用a[i]這個較小的元素更新b[j],因為原位置b[j]是大於a[i]的,所以我們要更新成更小的。演算法時間複雜度為o(nlogn)

最長單調遞增子串行

單調子串行包含有單調遞增子串行和遞減子串行,不失一般性,這裡只討論單調遞增子串行。首先,從定義上明確我們的問題。給定序列a1,a2,an,如果存在滿足下列條件的子串行 ai1 ai2 aim,其中i1即稱為乙個原序列的長度為m的單調遞增子串行,那麼,現在的問題是我們要找出乙個序列的最長的單調遞增子串...

最長單調遞增子串行

設計乙個o n2 時間的演算法,找出由n個數組成的序列的最長單調遞增子串行。輸入 第1個整數n 0分析 用陣列b 0 i 記錄以a i 0 i a k 並且 b k max b j 1 j i 1 所以 b i b k 1.如果存在k b k b k 並且 a i a k 即 b i 不是滿足條件的...

演算法導論15 4 6 最長單調遞增子串行

參考資料 程式設計之美 2.16 題目 給出乙個o nlogn 的演算法,使之能夠找出乙個n個數的序列中最長的單調遞增子串行。o n2 的比較好理解,沒有仔細研究,研究了下o nlogn 的解答和好多大神的分析才明白一些,發現玄妙無限呀 對於序列sn,考慮其長度為i的單調子列 1 i m 我們選取這...