南大算法設計與分析課程OJ答案(3)
問題 A: 動態中位數問題
時間限制: 1 Sec 內存限制: 8 MB提交: 866 解決: 102
提交 狀態 算法問答
題目描述
輸入一組整數a1, a2, …, an ,每輸入一個整數,輸出到此時為止的中位數。
中位數定義:如果數串的大小是偶數 2j,中位數是從小到大排列的第 j 個數;如果數串的大小是奇數 2j+1,中位數是從小到大排列的第 j+1 個數。
輸入
一組整數,數字和數字之間以空格隔開。輸出
一組整數,數字和數字之間以空格隔開。最後一個數後面也有空格。
第 i 個輸出的整數,是前 i 個輸入的中位數。
樣例輸入-18 -2 14 -20 -6 7 2 14 11 6
|
樣例輸出-18 -18 -2 -18 -6 -6 -2 -2 2 2
|
提示
時間復雜度請不要超過O(nlogn)。
由於輸入輸出的量會比較大,因此推薦使用c語言中的scanf和printf函數來進行輸入輸出,能比c++中cin和cout節省許多時間。
這裏本來有一行提示,但是由於老師上課不小心說漏嘴了,於是助教狠心地把它註釋掉了 ;
/*在處理該問題時,堆結構也許能給你帶來意想不到的幫助。*/
答案
比較尷尬,最近一忙就忘記做了,所以答案沒有經過oj測試,僅供參考(但測試用例一遍過了)
思路就是維護一個mid值、最大堆(存放比mid小的值)、最小堆(存放比mid大的值),每次讀入一個數,根據兩邊堆的大小來判斷當前值,具體怎麽判斷見代碼註釋,代碼中有關STL中堆的使用操作就不多數了,自行查閱。
代碼在VS2017上運行,在讀入輸出部分可能需要更改一下,scanf_s改scanf?
int main() { vector<int> heap_small; //這應該是個最大堆,存放著比mid小的元素 vector<int> heap_big; //這應該是個最小堆,存放著比mid大的元素 int mid =0; scanf_s("%d",&mid); printf("%d ",mid); int temp = 0; while (scanf_s("%d",&temp)!=EOF) {if (temp < mid) { if (heap_small.size() == heap_big.size()) { //左側和右側一樣大,將mid放入heap_big中,temp放入heap_small中,然後從heap_small選一個最大的作為mid heap_big.emplace_back(mid); push_heap(heap_big.begin(), heap_big.end(), [](int a, int b) {return b < a; }); heap_small.emplace_back(temp); push_heap(heap_small.begin(),heap_small.end()); pop_heap(heap_small.begin(), heap_small.end()); mid = heap_small.back(); heap_small.pop_back(); }else if (heap_small.size() == heap_big.size() - 1) { //右側比左側多一個,將temp放入heap_small中,然後mid還是為中位數 heap_small.emplace_back(temp); push_heap(heap_small.begin(), heap_small.end()); }else { //左側比右側多一個的情況應該不會出現 cout << "wrong" << endl; } } else { if (heap_small.size() == heap_big.size()) { //左側和右側一樣大,將temp放入heap_big中,mid還是中位數 heap_big.emplace_back(temp); push_heap(heap_big.begin(), heap_big.end(), [](int a, int b) {return b < a; }); } else if (heap_small.size() == heap_big.size() - 1) { //右側比左側多一個,將mid放入heap_small中,然後將temp放入heap_big中,然後從heap_big選一個最小的作為mid heap_small.emplace_back(mid); push_heap(heap_small.begin(), heap_small.end()); heap_big.emplace_back(temp); push_heap(heap_big.begin(), heap_big.end(), [](int a, int b) {return b < a; }); pop_heap(heap_big.begin(), heap_big.end(), [](int a, int b) {return b < a; }); mid = heap_big.back(); heap_big.pop_back(); } else { //左側比右側多一個的情況應該不會出現 cout << "wrong" << endl; } } printf("%d ",mid); } return 0; }
問題 B: 非完美二叉樹的高度與直徑
時間限制: 2 Sec 內存限制: 3 MB提交: 249 解決: 95
提交 狀態 算法問答
題目描述
記T為一棵二叉樹,樹中共有n個節點。
定義根節點的深度為0,其余節點的深度為其父節點的深度加1。T的高度定義為其葉節點深度的最大值。
定義樹中任意兩點a和b之間的距離為其間最短簡單路徑的長度。T的直徑定義為T中所有點對間距離的最大值。
輸入一棵二叉樹T,請計算它的高度和直徑。
輸入
輸入共三行。
第一行輸入n的值,表示樹中結點的總個數。
第二行為樹的前序遍歷表示,每個節點之間用空格隔開。
第三行為樹的中序遍歷表示,每個節點之間也用空格隔開。
輸出
輸出共三行。
第一行需要大家輸出一行字符串,它是“我已閱讀關於抄襲的說明”的英文翻譯,即:"I have read the rules about plagiarism punishment"。輸出此行的提交我們將認為已經完全閱讀並了解了“關於抄襲的說明”公告並同意關於抄襲的懲罰措施。
第二行輸出樹的高度。
第三行輸出樹的直徑。
樣例輸入10
0 1 9 3 8 4 2 7 5 6
3 9 8 1 2 4 0 5 7 6
|
樣例輸出I have read the rules about plagiarism punishment
3
5
|
提示
分治算法可以在O(n)的時間內完成相應的計算。
答案
沒法提交了,懶得寫了,網上答案挺多的
南大算法設計與分析課程OJ答案(3)