1. 程式人生 > 其它 >開學了,計算機的大學生們,送你們一篇經書,希望你們的四年不負年華!

開學了,計算機的大學生們,送你們一篇經書,希望你們的四年不負年華!

一、實踐名稱

maximum number in a unimodal array

一維陣列中的最大數字

二、問題描述

存在一個由n個不同元素組成的一維陣列,元素從小遞增至最大資料後遞減,即求出峰值資料,該演算法的時間複雜度已被規定為Olog n

三、演算法描述

1)在主函式如題目所示定義出n用於存放輸入資料的數量,和a[1000]用於存放陣列數值,並依次輸入

2)定義一個int 型別函式bio(int a[],int left,int right,int n)用於進行二分查詢,其中a存放輸入陣列,left為查詢範圍的最左側下邊,n-1為查詢範圍的最右邊下標,nmain函式中用於存放輸入資料的總數量

3)bio函式中定義一個int型別的資料m,用於存放(left+right/2也就是查詢範圍中間資料的下標

left<=right時進行以下判斷:

  1. bio函式中首先用if(m == 0)來判斷該範圍中資料是否只有一個,若只有一個則峰值為該資料,break,返回a[m]
  2. 再用if(a[m - 1] < a[m] && a[m + 1] < a[m])來判斷m下標所指向的資料是否為峰值,若滿足條件返回,breaka[m]
  3. 若以上條件接不滿足,則進行以下判斷,若a[m - 1] > a[m],說明峰值出現在了本次搜查範圍的左邊,則需要return bio(a,left,m-1,n)
    進行遞迴操作在leftm-1的範圍內再次查詢;若a[m +1] > a[m],說明峰值出現在了本次搜查範圍的右邊,則需要return bio(a,m+1,right,n)進行遞迴操作在m+1right的範圍內再次查詢

4)main函式中輸出bio(a,0,n-1,n)return 0結束運算

四、演算法時間複雜度以及空間複雜度的分析(分析過程)

時間複雜度:

1)bio函式中運用的查詢方法為用遞迴呼叫實現二分搜尋,則時間複雜度為Olog2n

2)在if(m == 0)if(a[m - 1] < a[m] && a[m + 1] < a[m])a[m - 1] > a[m]

a[m +1] > a[m]這四個判斷條件中,時間複雜度都為O1

綜上所述時間複雜度為Olog2n

空間複雜度:

bio函式中,每次遞迴都會產生一個m進行儲存(left+right/2,則空間複雜度為Olog2n

五、心得體會

  1. 第一次打出來的程式碼會出現執行超時的情況,後來發現了自己的低階錯誤,我只是對if(a[m - 1] < a[m] && a[m + 1] < a[m])這個條件進行了判斷後break,但是忘記return了,所以出現了執行超時(真的很低階,下次需要注意)
  2. 在改正了1中的錯誤後,程式碼出現了部分錯誤的判斷,我就意識到了出現邊界溢位的情況,在這條程式碼中if(a[m - 1] < a[m] && a[m + 1] < a[m])如果m=0的話則m-1會出現溢位不合法,所以我後來加上了if(m == 0)來判斷該範圍中資料是否只有一個後,程式碼就可以完全通過了!

六、分治法的個人體會和思考

  1. 分治法需要特別嚴謹的研究,例如leftright要不要改變,變成mid還是mid+1或者mid-1,一般用例題中簡單的例子就可以推算出來,所以分治法的在打程式碼之前話較長一段時間進行分析我認為是非常有必要的。
  2. 通過這次實驗的兩道題和平時作業的題目我發現了,一般陣列用二分查詢還是較為簡單的,但需要注意的是不同題目的陣列輸入排列順序不同,所以有時候用紙畫圖後會更明確判斷條件。
  3. 類似於切蛋糕問題和本次實驗中找函式的解的問題,特別需要注意其精度和輸出格式,如小數點後需保留幾位的問題,這兩個方面在日常打程式碼的過程中都栽過跟頭,所以需要特別注意
  4. 在二分法的問題中,需要特別注意的就是邊界問題,除了邊界的數值之外,還需要特別注意一些例如應該是< 還是<=的問題,如果邊界沒有正確判斷的話,遞迴容易進入一個死迴圈