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