4.核心**
5.結果
6.源**
本週為兩節習題課,在習題課的最後,討論到了這一題,沒有討論出結果。本來有一些思路,恰好看到了這一題,於是將其解決。
這道題本來解法不難,正常思路有兩種,一種是直接講兩個陣列排序,然後直接找到中間數值,其演算法複雜度為o(m + n)
;另一種是從兩個陣列的首部開始找,每找到乙個小數,指標就向下移動一格,直到移動了(m + n) / 2
其複雜度也為o(m + n)
。因此兩種演算法都不符合題目o(log(m + n))
的要求。我們看題目要求,很容易聯想到,
log
的複雜度,說明要用到二分
之類的方法。將本題模擬做尋找k
值,(k = (m + n) / 2
)。認真思考,二分的實質即是:每次剔除一般的值,一次遞迴,一直剔除到需要的值出現。如果是在乙個陣列中尋找,很簡單,每次將兩份數值中的乙份刪去即可,但是如果是兩個陣列,那又如何實現呢?想象將兩個陣列同時二分,分成4段,能否得到可定可以刪去的一段呢?是可以的,舉個簡單的例子:
我們來比較x
與y
的大小,如果x > y
那麼就說明mid n
左邊的一段一定是可以刪去的,若是x < y
,那麼結果相反,刪去的即是mid m
左邊的一段。一次操作過後,剩下的即是在剩下的三段中間找尋k - mid n/mid m
大的值。那麼新的問題又出現了:如果在遞迴的過程中,某一段的
mid m/mid n > k
了應該怎麼辦?其實也很好解決,在我們二分的時候,將步長設定為k / 2
即可。現在考慮,完整的演算法應該如何劃分,選擇。
這樣,每次我們就能夠從中間刪除k / 2
長度的區間。但是我們的問題又來了,如果陣列不夠
k / 2
的長度呢?不就會越界訪問了嗎?因此,區間設定應該為min(k / 2, m_length, n_length)
。接下來,我們要思考,終點在**。實際上,終點就是k == 1
或者m\n長度為0
的時候。(m + n)
是奇數,尋找(m + n) / 2
;否則尋找((m + n) / 2 + (m + n) / 2 + 1) / 2
。尋找
k
位演算法://如果有陣列為空,在剩下的陣列中尋找即可
if (mlen == 0) else if (nlen == 0)
//只找一位,避免死迴圈
if(k == 1)
int mmid, nmid;
//避免越界,又要保證刪去盡可能多的資料,因此選擇長的陣列作為起始分界點
if (nlen > mlen) else
//判斷
//只找一位,避免死迴圈
if(k == 1)
int mmid, nmid;
//避免越界,又要保證刪去盡可能多的資料,因此選擇長的陣列作為起始分界點
if (nlen > mlen) else
//判斷
if(m[mstart + mmid - 1] < n[nstart + nmid - 1]) else else
} }
演算法分析與設計(第六周) 更新中
本週知識要點 6.1 子串行和定義 定長子序列和演算法 不定長子序列和演算法,最大子串行和演算法 子串行積演算法 6.2 找主元演算法 遞迴,分段處理 附加數學證明 問題描述 給一段數列 m 子串行定長 n 問何時子串行和最大。思路 運用兩重迴圈 一重迴圈用來移動視窗 即起始位置 第二重迴圈求和。此...
系統分析與設計第六周作業
二 建模練習題 確定系統邊界,寫明系統名稱 確定參與者 確定參與者之間的關係 根據需求創造用例 確定參與者與用例之間的關係 確定用例與用例之間的關係 將其他支援用例的系統放置在系統框的右邊 為什麼相似系統的用例圖是相似的?答 因為在相似的系統中,使用者需求是相似的,對應的用例場景也相似,所以用例圖也...
mooc程式設計與演算法(三)第六周 多型
派生類的指標可以賦值給基類指標 通過基類指標用基類和派生類中的同名虛函式時 若該指標指向乙個基類的物件,那麼被呼叫是基類的虛函式 若該指標指向乙個派生類的物件,那麼被呼叫的是派生類的虛函式。派生類的物件可以賦值給基類的引用 通過基類引用呼叫基類和派生類中的同名虛函式時 若該引用引用的是乙個基類的物件...