完成日期:2017/9/26
1. 實踐題目
求兩個有序序列的中位數
2. 問題描述
已知有兩個等長的非降序序列s1, s2, 設計函式求s1與s2並集的中位數。
有序序列a0 ,a1 ,⋯,an−1 的中位數指a(n−1)/2 的值,即第⌊(n+1)/2⌋個數(a0 為第1個數)。
要求時間複雜度為o(logn)
3. 演算法描述
分別求出序列a和序列b的中位數a[mid1]和b[mid2],比較兩個中位數的大小,會出現三種情況:
1). a[mid1] = b[mid2]:即a[mid1]為兩個序列的中位數;
2). a[mid1] < b[mid2]:則中位數會出在a[mid1]和b[mid2]之間,在序列a
中刪除a[mid1]之前的元素得到序列a1,在序列b中刪除b[mid2]之後的元素得到序列b1;
3). a[mid1] > b[mid2]: 則中位數會出在b[mid2]和a[mid1]之間,在序列a
中刪除a[mid1]之後的元素得到序列a1,在序列b中刪除b[mid2]之前的元素得到序列b1;
在a1和b1中分別求出中位數,重複上述步驟1 2 3,如果得到兩個序列都只剩乙個元素,則兩個元素中較小的那個就是所求。
注意:因為要求每次兩個序列要捨棄的長度要相等,因此序列有奇數個元素和偶數個元素要分開討論。
4. 演算法時間及空間複雜度分析
因為每次求得兩個序列的中位數之後,得到的兩個子串行的長度都是上兩個序列的一半,因為迴圈共執行log2n次,因此時間複雜度為o(logn)。
因為演算法除了簡單的變數以外,沒有與n規模相關的輔助變數,因此空間複雜度為o(1)。
5. 程式**
#include
using
namespace
std;
void searchz(int a, int b, int k)
else
if (a[mid1] < b[mid2])
else
}else
else
}
}if (a[l1] < b[l2])
else
return;
} int main()
for (int j = 0; j < k; j++)
searchz(m, n, k);
return
0;}
6. 程式執行截圖
7. 心得體會
看到題目所要求的時間複雜度為o(logn)時,結合之前所學的歸併排序,知道如果要演算法時間的數量級為logn的話,每迴圈一次之後資料的規模都要減半,因此首先需要思考如何在每一次迴圈之後n要變成n/2,也就是運用上mid。
然後演算法的框架出來之後,一開始執行的時候出現了無限迴圈的情況,後來思考了一下,發現自己忽略兩個序列每次都要捨棄的長度要相同,因此需要分奇偶討論。
後來老師提出了乙個不需要分奇偶討論的方法,就是mid1 = (left1 + right1) /2, mid2 = (left2 + right2+1)/2,這樣對奇數個元素時沒有影響,但是又能保證在偶數個元素時,兩個序列捨棄的長度相同,但是這種做法我在實施的時候,遇到了乙個很嚴重的問題:
思考了很久只得出了乙個解決方法= =,就是在最後每個序列只剩下2個元素的時候,對這四個元素進行排序得到中位數,這樣對時間複雜度沒有做什麼貢獻,但是會有些累贅。除了這個以外就沒想到其他的方法了。
遞迴 演算法學習
遞迴按照遞迴方式可以分為直接遞迴和間接遞迴 1.直接遞迴 遞迴過程p直接呼叫自己 2.間接遞迴 p包含另乙個過程d,而d又呼叫p 遞迴例項 1.漢諾塔問題 include include void hanoi int n,char a,char b,char c int main void 2.八皇...
遞迴演算法學習
所謂的遞迴函式就是在函式體內呼叫本函式。使用遞迴函式一定要注意,處理不當就會進入死迴圈。遞迴函式只有在特定的情況下使用 比如階乘問題 遞迴演算法測試 10的階乘 function f num else console.log 10 的結果為 f 10 請實現乙個fibonacci函式,要求其引數和返...
演算法學習筆記 遞迴
漢諾塔問題 有種說法我覺得很好,所謂遞迴,就是利用大道至簡的思想,把乙個大的複雜的問題層層轉換為乙個小的和原問題相似的問題來求解的這樣一種策略。優點缺點 遞迴給人的感覺是驚豔,它往往能給我們帶來非常簡潔非常直觀的 形勢,從而使我們的編碼大大簡化。效率往往很低,費時和費記憶體空間。在遞迴呼叫的過程當中...