二叉樹

輸入一棵二叉樹前序遍歷和中序遍歷的結(jié)果,請重建該二叉樹。二叉樹中每個節(jié)點的值都互不相同;
輸入的前序遍歷和中序遍歷一定合法。
給定:
前序遍歷是:[3, 9, 20, 15, 7]
中序遍歷是:[9, 3, 15, 20, 7]

返回:[3, 9, 20, null, null, 15, 7, null, null, null, null]
返回的二叉樹如下所示:
3
/
9 20
/
15 7
遞歸版本比較容易,重點是非遞歸版本
(遞歸) O(n)
遞歸建立整棵二叉樹:先遞歸創(chuàng)建左右子樹,然后創(chuàng)建根節(jié)點,并讓指針指向兩棵子樹。

具體步驟如下:

先利用前序遍歷找根節(jié)點:前序遍歷的第一個數(shù),就是根節(jié)點的值;
在中序遍歷中找到根節(jié)點的位置 k,則 k左邊是左子樹的中序遍歷,右邊是右子樹的中序遍歷;
假設(shè)左子樹的中序遍歷的長度是 l,則在前序遍歷中,根節(jié)點后面的 l個數(shù),是左子樹的前序遍歷,剩下的數(shù)是右子樹的前序遍歷;
有了左右子樹的前序遍歷和中序遍歷,我們可以先遞歸創(chuàng)建出左右子樹,然后再創(chuàng)建根節(jié)點;
時間復(fù)雜度分析
我們在初始化時,用哈希表(unordered_map<int,int>)記錄每個值在中序遍歷中的位置,這樣我們在遞歸到每個節(jié)點時,在中序遍歷中查找根節(jié)點位置的操作,只需要 O(1)的時間。此時,創(chuàng)建每個節(jié)點需要的時間是 O(1),所以總時間復(fù)雜度是 O(n)。
···
class Solution {
public:
unordered_map<int,int> pos;

TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
    int n = preorder.size();//記錄節(jié)點的個數(shù),前序和中序的結(jié)果是一樣的
    for (int i = 0; i < n; i ++ )//遍歷開始
        pos[inorder[i]] = i;//把中序遍歷的每個位置用哈希存起來,這樣查找辦成O1,某個值的位置是下標
    return dfs(preorder, inorder, 0, n - 1, 0, n - 1);//前序和中序的起始和終止
}

TreeNode* dfs(vector<int>&pre, vector<int>&in, int pl, int pr, int il, int ir)
{
    if (pl > pr) return NULL;//邊界條件
    int k = pos[pre[pl]] - il;//算出前序遍歷的第一個節(jié)點在中序的位置,就是跟節(jié)點的位置。
    TreeNode* root = new TreeNode(pre[pl]);//重建
    root->left = dfs(pre, in, pl + 1, pl + k, il, il + k - 1);//PL是跟節(jié)點,+1就是左邊的樹,K是左邊樹的長度,左子樹在中序中是IL起始,K左邊就要減去1
    root->right = dfs(pre, in, pl + k + 1, pr, il + k + 1, ir);
    return root;//右子樹在前序中是開始加跟的后面一個,結(jié)尾是末尾,在中序中是跟后面的
}

};





?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容