1. 實踐題目ios
7-3 兩個有序序列的中位數算法
2. 問題描述數組
已知有兩個等長的非降序序列S1, S2, 設計函數求S1與S2並集的中位數。有序序列A0,A1,⋯,AN−1的中位數指A(N−1)/2的值,即第⌊(N+1)/2⌋個數(A0爲第1個數)。框架
Input函數
在一行中輸出兩個輸入序列的並集序列的中位數。spa
Sample
設計
輸入1:指針
5調試
1 3 5 7 9code
2 3 4 5 6
輸出1:
4
輸入2:
6
-100 -10 1 1 1 1
-50 0 2 3 4 5
輸出2:
1
3. 算法描述
1 #include <iostream> 2 using namespace std; 3 void Arrange(int s1[], int s2[], int N) //用於求二者並集,並輸出結果的函數 4 { 5 int X = N + N; 6 int s3[X]; //定義一個s3數組,存儲二者的並集,空間大小爲s1與s2數組大小之和 7 int i = 0, j = 0, k = 0; //定義三個指針,分別做爲s一、s二、s3數組的指針 8 while(i<N && j<N) //當s一、s2指針均沒指到結尾時,遍歷s一、s2,將每一步獲得的最小元素放入s3中 9 { 10 if(s1[i] < s2[j]) 11 { 12 s3[k] = s1[i]; 13 k++, i++; 14 } 15 else 16 { 17 s3[k] = s2[j]; 18 k++, j++; 19 } 20 } 21 while(i<N) //當s2指到結尾,s1未指到結尾時,繼續遍歷s1,將剩下的最小元素放入s3 22 { 23 s3[k] = s1[i]; 24 k++, i++; 25 } 26 while(j<N) //當s1指到結尾,s2未指到結尾時,繼續遍歷s2,將剩下的最小元素放入s3 27 { 28 s3[k] = s2[j]; 29 k++, j++; 30 } 31 cout << s3[(X-1)/2]; //在函數中輸出s3的中位數 32 } 33 34 int main() 35 { 36 int N; 37 cin >> N; 38 int s1[N], s2[N]; 39 for(int i=0; i<N; i++) 40 { 41 cin >> s1[i]; 42 } 43 for(int i=0; i<N; i++) 44 { 45 cin >> s2[i]; 46 } 47 if( s1[(N-1)/2] == s2[(N-1)/2] ) 48 { 49 cout << s1[(N-1)/2]; 50 return 0; 51 } 52 Arrange(s1, s2, N); 53 return 0; 54 }
4. 算法時間及空間複雜度分析
時間複雜度:
main()函數中有2個for循環,用於進行程序的輸入,它們的時間複雜度均爲O(n),其他語句的時間複雜度均爲O(1);
Arrange(s1, s2, N)函數中,第一個while循環內嵌的是if和else條件判斷語句,因此它的時間複雜度爲O(n+n),即O(n)級別,剩餘的兩個while循環也同理。
所以,本算法的時間複雜度爲O(n)。
空間複雜度:
由於變量只建立一次,且無需另外開闢輔助空間,所以,本算法的空間複雜度爲O(1)。
5. 心得體會
寫代碼時要細心,寫完以後要檢查,運行結果出錯時不要想固然。
若程序結果出錯時,要先檢查是不是算法大框架的問題。
本組在進行本程序的開發時,最初錯將第10行的if(s1[i] < s2[j])錯寫爲if(s1[i] < s2[i]),致使沒法在全部狀況下均得到Accepted結果。
在使用第一個Sample進行調試時,輸出的是4而非5,我想固然覺得排序出來的s3數組是正確的,產生問題的緣由在於N爲奇數,因而增長了奇數N狀況下的條件判斷,結果仍錯誤。
使用IDE進行調試事後,發現s3數組內部元素除了前幾個之外其他的都是亂序,又增長了幾個判斷條件(也包括回溯指針等過程)均沒法成功實行。
而後小組另外一位成員提示:只需將i改成j便可成功,遂實行,結果爲Accepted。
今後得到教訓——之後程序運行結果出錯時應先看大方向,把大方向弄無誤了以後再去整理細節,不然就會犯鑽牛角尖的錯誤。