W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
Question
給定一個(gè)二叉樹(shù)的前序遍歷 preorder
和中序遍歷 inorder
,請(qǐng)從中構(gòu)建二叉樹(shù),返回二叉樹(shù)的根節(jié)點(diǎn)。
圖 12-5 構(gòu)建二叉樹(shù)的示例數(shù)據(jù)
原問(wèn)題定義為從 preorder
和 inorder
構(gòu)建二叉樹(shù),其是一個(gè)典型的分治問(wèn)題。
根據(jù)以上分析,這道題是可以使用分治來(lái)求解的,但如何通過(guò)前序遍歷 preorder
和中序遍歷 inorder
來(lái)劃分左子樹(shù)和右子樹(shù)呢?
根據(jù)定義,preorder
和 inorder
都可以被劃分為三個(gè)部分。
[ 根節(jié)點(diǎn) | 左子樹(shù) | 右子樹(shù) ]
,例如圖 12-5 的樹(shù)對(duì)應(yīng) [ 3 | 9 | 2 1 7 ]
。[ 左子樹(shù) | 根節(jié)點(diǎn) | 右子樹(shù) ]
,例如圖 12-5 的樹(shù)對(duì)應(yīng) [ 9 | 3 | 1 2 7 ]
。以上圖數(shù)據(jù)為例,我們可以通過(guò)圖 12-6 所示的步驟得到劃分結(jié)果。
inorder
中的索引,利用該索引可將 inorder
劃分為 [ 9 | 3 | 1 2 7 ]
。inorder
劃分結(jié)果,易得左子樹(shù)和右子樹(shù)的節(jié)點(diǎn)數(shù)量分別為 1 和 3 ,從而可將 preorder
劃分為 [ 3 | 9 | 2 1 7 ]
。圖 12-6 在前序和中序遍歷中劃分子樹(shù)
根據(jù)以上劃分方法,我們已經(jīng)得到根節(jié)點(diǎn)、左子樹(shù)、右子樹(shù)在 preorder
和 inorder
中的索引區(qū)間。而為了描述這些索引區(qū)間,我們需要借助幾個(gè)指針變量。
preorder
中的索引記為 inorder
中的索引記為 inorder
中的索引區(qū)間記為 如表 12-1 所示,通過(guò)以上變量即可表示根節(jié)點(diǎn)在 preorder
中的索引,以及子樹(shù)在 inorder
中的索引區(qū)間。
表 12-1 根節(jié)點(diǎn)和子樹(shù)在前序和中序遍歷中的索引
根節(jié)點(diǎn)在 preorder 中的索引 |
子樹(shù)在 inorder 中的索引區(qū)間 |
|
---|---|---|
當(dāng)前樹(shù) | ||
左子樹(shù) | ||
右子樹(shù) |
請(qǐng)注意,右子樹(shù)根節(jié)點(diǎn)索引中的
圖 12-7 根節(jié)點(diǎn)和左右子樹(shù)的索引區(qū)間表示
為了提升查詢 hmap
來(lái)存儲(chǔ)數(shù)組 inorder
中元素到索引的映射。
build_tree.cpp
/* 構(gòu)建二叉樹(shù):分治 */
TreeNode *dfs(vector<int> &preorder, unordered_map<int, int> &inorderMap, int i, int l, int r) {
// 子樹(shù)區(qū)間為空時(shí)終止
if (r - l < 0)
return NULL;
// 初始化根節(jié)點(diǎn)
TreeNode *root = new TreeNode(preorder[i]);
// 查詢 m ,從而劃分左右子樹(shù)
int m = inorderMap[preorder[i]];
// 子問(wèn)題:構(gòu)建左子樹(shù)
root->left = dfs(preorder, inorderMap, i + 1, l, m - 1);
// 子問(wèn)題:構(gòu)建右子樹(shù)
root->right = dfs(preorder, inorderMap, i + 1 + m - l, m + 1, r);
// 返回根節(jié)點(diǎn)
return root;
}
/* 構(gòu)建二叉樹(shù) */
TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {
// 初始化哈希表,存儲(chǔ) inorder 元素到索引的映射
unordered_map<int, int> inorderMap;
for (int i = 0; i < inorder.size(); i++) {
inorderMap[inorder[i]] = i;
}
TreeNode *root = dfs(preorder, inorderMap, 0, 0, inorder.size() - 1);
return root;
}
圖 12-8 展示了構(gòu)建二叉樹(shù)的遞歸過(guò)程,各個(gè)節(jié)點(diǎn)是在向下“遞”的過(guò)程中建立的,而各條邊(即引用)是在向上“歸”的過(guò)程中建立的。
圖 12-8 構(gòu)建二叉樹(shù)的遞歸過(guò)程
每個(gè)遞歸函數(shù)內(nèi)的前序遍歷 preorder
和中序遍歷 inorder
的劃分結(jié)果如圖 12-9 所示。
圖 12-9 每個(gè)遞歸函數(shù)中的劃分結(jié)果
設(shè)樹(shù)的節(jié)點(diǎn)數(shù)量為 dfs()
)使用
哈希表存儲(chǔ) inorder
元素到索引的映射,空間復(fù)雜度為
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: