置頂

我的 VPython 教學文件 (HackMD 版本)

VPython 教學文件目錄 安裝及測試 基本語法 等速度直線運動 自由落下 終端速度 水平抛射 使用For迴圈計算水平抛射資料 斜向抛射 圓周運動 簡諧運動 單擺 木塊彈簧系統分離 重力及簡諧 行星運動 相疊木塊 雙重簡諧運動 一維彈性碰撞 ...

熱門文章

2026年3月18日 星期三

ZeroJudge 解題筆記:c126. 00536 - Tree Recovery

作者:王一哲
日期:2026年3月18日


ZeroJudge 題目連結:c126. 00536 - Tree Recovery

解題想法


這題需要知道二元樹的結構及走訪的順序。前序走訪的順序為父節點、左子節點、右子節點,中序走訪的順序為左子節點、父節點、右子節點,後序走訪的順序為左子節點、右子節點、父節點。因此,從測資中讀到的前序走訪資料開頭就是根節點,測資中的中序走訪資料左側為根節點的左子樹,右側為根節點的右子樹。依照這樣的原則設計從前序走訪、中序走訪資料建立後序走訪資料的函式。

Python 程式碼


用字串儲存二元樹走訪的資料,用時間約為 7 ms,記憶體約為 2.8 MB,通過測試。
import sys

def build_tree(preorder, inorder):
    if not preorder or not inorder: return ""  # 如果沒有資料,回傳空字串
    root = preorder[0]  # 前序走訪開頭為根節點
    root_idx = inorder.find(root)  # 找到中序走訪資料中根節點的索引值
    left_inorder = inorder[:root_idx]  # 中序走訪資料中左子樹資料
    right_inorder = inorder[root_idx+1:]  # 中序走訪資料中右子樹資料
    left_preorder = preorder[1:1+len(left_inorder)]  # 前序走訪資料中左子樹資料
    right_preorder = preorder[1+len(left_inorder):]  # 前序走訪資料中右子樹資料
    left_postorder = build_tree(left_preorder, left_inorder)  # 遞迴,找左子樹後序走訪資料
    right_postorder = build_tree(right_preorder, right_inorder)  # 遞迴,找右子樹後序走訪資料
    return left_postorder + right_postorder + root  # 組合成答案

result = []
lines = sys.stdin.readlines()
for line in lines:
    if not line.strip(): continue
    result.append(f"{build_tree(*line.split())}\n")
sys.stdout.write("".join(result))

用串列儲存二元樹走訪的資料,用時間約為 7 ms,記憶體約為 2.8 MB,通過測試。
import sys

def build_tree(preorder, inorder):
    if not preorder or not inorder: return []  # 如果沒有資料,回傳空串列
    root = preorder[0]  # 前序走訪開頭為根節點
    root_idx = inorder.find(root)  # 找到中序走訪資料中根節點的索引值
    left_inorder = inorder[:root_idx]  # 中序走訪資料中左子樹資料
    right_inorder = inorder[root_idx+1:]  # 中序走訪資料中右子樹資料
    left_preorder = preorder[1:1+len(left_inorder)]  # 前序走訪資料中左子樹資料
    right_preorder = preorder[1+len(left_inorder):]  # 前序走訪資料中右子樹資料
    left_postorder = build_tree(left_preorder, left_inorder)  # 遞迴,找左子樹後序走訪資料
    right_postorder = build_tree(right_preorder, right_inorder)  # 遞迴,找右子樹後序走訪資料
    return left_postorder + right_postorder + [root]  # 組合成答案

result = []
lines = sys.stdin.readlines()
for line in lines:
    if not line.strip(): continue
    ans = "".join(build_tree(*line.split()))
    result.append(f"{ans}\n")
sys.stdout.write("".join(result))


C++ 程式碼


使用時間約為 1 ms,記憶體約為 304 kB,通過測試。
#include <iostream>
#include <string>
using namespace std;

string build_tree(string preorder, string inorder) {
    if (preorder.empty() || inorder.empty()) return "";
    char root = preorder[0];
    size_t root_idx = inorder.find(root);
    string left_inorder = inorder.substr(0, root_idx);
    string right_inorder = inorder.substr(root_idx+1);
    string left_preorder = preorder.substr(1, left_inorder.size());
    string right_preorder = preorder.substr(1+left_inorder.size());
    string left_postorder = build_tree(left_preorder, left_inorder);
    string right_postorder = build_tree(right_preorder, right_inorder);
    return left_postorder + right_postorder + root;
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    string preorder, inorder;
    while(cin >> preorder >> inorder) {
        cout << build_tree(preorder, inorder) << "\n";
    }
    return 0;
}


沒有留言:

張貼留言