演算法第三章上機實踐報告
1.實踐報告
1.1問題描述
設計一個O(n^2)時間的演算法,找出由n個數組成的序列的最長單調遞增子序列。
1.2演算法描述
求解該問題須記錄的資料我們用兩個陣列(num,D)和兩個變數(max,t)表示。
arr[i]:表示輸入的n個數組中的第i個;
num[i]:表示以arr[i]為尾元素的單調遞增序列的最大值;
D[i]:表示以arr[i]為首元素的序列的最長單調遞增子序列;
max:記錄填表(num)過程中的最大值;
t:記錄max所在元素的下標i。
用動態規劃的思想,分為以下四個步驟:
①問題結構分析:該問題考察的是最長單調遞增子序列的問題,最長單調遞增子序列是由相對較短的單調遞增子序列構成,這就印證了最長單調遞增子序列與相對較短的單調遞增子序列之間可以建立遞推關係;
②遞推關係建立:見1.3.1;
③自底向上計算:從左到右填表(陣列arr和陣列D);
④最優方案追蹤:遍歷陣列D。
1.3問題求解
1.3.1根據最優子結構性質,列出遞迴方程式
首先,從D[1]開始。
當arr[i-1]<arr[i]時,分為兩種情況:
①num[i-1]+1<max+1,若arr[i]>arr[t],則num[i]=max+1;
若arr[i]<=arr[t],則從i-1開始往前遍歷,找到符合條件(arr[i]>arr[k])的最大的num[k],即num[i]=num[k]+1;
②num[i-1]+1>=max+1,num[i]=num[i-1]+1;
當arr[i-1]>=arr[i]時,則從i-2開始往前遍歷,找到符合條件(arr[i]>arr[k])的最大的num[k],即num[i]=num[k]+1;
以此類推,不斷迴圈,從左往右填寫陣列arr和陣列D;
最後,遍歷陣列D,找到其最大值,即為題目所求最長單調遞增子序列的長度。
1.3.2給出填表法中表的維度、填表範圍和填表順序
表的維度:陣列arr和陣列D均為一維陣列;
填表範圍:陣列D為從1到n;陣列arr為從j(D陣列的下標)到n;
填表順序:陣列arr和陣列D均為從左到右的順序;
1.3.3分析該演算法的時間和空間複雜度
時間複雜度:該演算法用了兩層迴圈(遍歷陣列D以及遍歷陣列arr),所以時間複雜度為O(n^2);
空間複雜度:需要填寫兩個表(陣列arr和陣列D)以及兩個變數(max和t),所以空間複雜度為O(2n)+O(1)=O(n)。
1.4心得體會
1.4.1本次實踐收穫
加深了對動態規劃演算法的理解,能夠更加熟練地運用動態規劃演算法,並且在處理臨界條件和特殊情況有了更深入的思考並取得較大的進步。
1.4.2本次實踐疑惑
有時候處理陣列時可以用寫在main函式裡,不會出現問題,有時候又必須定義成全域性陣列才不會出錯,感覺不太懂。
處理方法:定義成全域性陣列就沒錯了。
2.對動態規劃演算法的理解和體會
動態規劃演算法與分治法類似,其基本思想也是將帶求解問題分解成若干子問題
但是經分解得到的子問題往往不是互相獨立的。不同問題的數目常常有多項式量級。在用分治法求解時,有些子問題被重複計算了許多次。
如何減少子問題的重複計算就是動態規劃演算法的關鍵解決思想!