已知前序(后序)遍歷序列和中序遍歷序列構建二叉樹(Leetcode相關題目)


1.文字描述:

已知一顆二叉樹的前序(后序)遍歷序列和中序遍歷序列,如何構建這棵二叉樹?

以前序為例子:

前序遍歷序列:ABCDEF

中序遍歷序列:CBDAEF

前序遍歷先訪問根節點,因此前序遍歷序列的第一個字母肯定就是根節點,即A是根節點;然后,由於中序遍歷先訪問左子樹,再訪問根節點,最后訪問右子樹,所以我們找到中序遍歷中A的位置,然后A左邊的字母就是左子樹了,也就是CBD是根節點的左子樹;同樣的,得到EF為根節點的右子樹。

將前序遍歷序列分成BCD和EF,分別對左子樹和右子樹應用同樣的方法,遞歸下去,二叉樹就成功構建好了。如下圖:

 

 

假如已知的是中序和后序遍歷的序列,原理也一樣。由於后序是先訪問左子樹,然后訪問右子樹,最后訪問根節點,因此我們確定后序遍歷序列的最后一個字母為根節點。其他步驟一樣,用中序遍歷序列找出兩棵子樹,再進行同樣的操作。

 

2.代碼實現:

(1)已知前序和中序:

Leetcode題目:

105 Construct Binary Tree from Preorder and Inorder Traversal(https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/description/)

代碼:

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return buildTree(preorder, inorder, 0, preorder.size() - 1, 0, inorder.size() - 1);
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder, int preStart, int preEnd, int inStart, int inEnd) {
        if (preStart > preEnd || inStart > inEnd) return NULL;
        TreeNode *res;
        res = new TreeNode(preorder[preStart]);
        int flag;
        for (int i = inStart; i <= inEnd; i++) {
            if (preorder[preStart] == inorder[i]) {
                flag = i;
                break;
            }
        }
        res->left = buildTree(preorder, inorder, preStart + 1, preStart + flag - inStart, inStart, flag - 1);
        res->right = buildTree(preorder, inorder, preStart + flag - inStart + 1, preEnd, flag + 1, inEnd);
        return res;
    }
};

一開始我采用的做法是遇到的每棵子樹都用新的vector數組來存放它的中序和前序遍歷序列,但這樣又浪費空間又增加時間,我們只要用原來的vector數組就可以了。

因此我們要用preStart,preEnd,inStart和inEnd來保存序列開始和結束的位置。比較容易得出的是inStart和inEnd這兩個位置;難理解的是左子樹的preEnd和右子樹的preStart。但是我們求出左子樹的preEnd后,只要加1就是右子樹的preStart了。而要求左子樹的preEnd我們可以通過中序來求出左子樹的元素個數,然后就可以求出這個位置了。

 

(1)已知中序和后序:

Leetcode題目:

106 Construct Binary Tree from Inorder and Postorder Traversal(https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/description/)

代碼:

class Solution {
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        return buildTree(inorder, postorder, 0, inorder.size() - 1, postorder.size() - 1, 0);
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder, int inStart, int inEnd, int postEnd, int postStart) {
        if (inStart > inEnd || postEnd < postStart) {
            return NULL;
        }
        int flag;
        TreeNode *res = new TreeNode(postorder[postEnd]);
        for (int i = inStart; i <= inEnd; i++) {
            if (inorder[i] == postorder[postEnd]) {
                flag = i;
                break;
            }
        }
        res->left = buildTree(inorder, postorder, inStart, flag - 1, postStart - inStart + flag - 1, postStart);
        res->right = buildTree(inorder, postorder, flag + 1, inEnd, postEnd - 1, postEnd - inEnd + flag);
        return res;
    }
};

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM