1. 程式人生 > >南大算法設計與分析課程OJ答案(3)

南大算法設計與分析課程OJ答案(3)

完美 語言 偶數 使用 課程 nbsp problems AS btn

問題 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)