1. 程式人生 > >《劍指offer》學習筆記_面試題7_重建二叉樹

《劍指offer》學習筆記_面試題7_重建二叉樹

  • 一、前序遍歷與中序遍歷重建二叉樹

  • 1.題目描述

      輸入一顆二叉樹的前序遍歷序列和中序遍歷序列,請根據這兩個序列重建一棵二叉樹。(假設輸入的前序遍歷和中序遍歷的結果都不包含重複的數字)

  • 2.思路

      前序遍歷的第一個數就是二叉樹的根結點,這個根結點通常是在中序遍歷的中間位置。在中序遍歷中,根結點左邊的數都在二叉樹的左子樹中,右邊的數都在二叉樹的右子樹中。因此通過中序遍歷,可以確定左子樹結點的個數和右子樹結點的個數。在前序遍歷中,根結點後面先是左子樹的所有結點,之後是右子樹的所有結點。

前序遍歷和中序遍歷的關係:

  • 3.C++實現

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(preorder.size()==0)return nullptr;
        if(preorder.size()!=inorder.size())return nullptr;
        return create(preorder,inorder,0,preorder.size()-1,0,inorder.size()-1);
    }
    /*
    ps:前向遍歷的開始位置;
    pe:前向遍歷的結束位置;
    is:中序遍歷的開始位置;
    ie:中序遍歷的結束位置;
    */
    TreeNode* create(vector<int>& preorder,vector<int>& inorder,int ps,int pe,int is,int ie){
        if(ps>pe)return nullptr;
        TreeNode* node = new TreeNode(preorder[ps]);
        int pos;//儲存前序遍歷的第一個數字在中序遍歷中的位置
        for(int i = is;i<=ie;i++){
            if(inorder[i]==node->val){
                pos = i;
                break;
            }
        }
        int leftLen = pos - is;//左子樹中的結點數
        node->left = create(preorder,inorder,ps+1,ps+leftLen,is,pos-1);
        node->right = create(preorder,inorder,ps+leftLen+1,pe,pos+1,ie);
        return node;
    }
};
  • 二、後序遍歷與中序遍歷重建二叉樹

  • 1.題目描述

      輸入一顆二叉樹的後序遍歷序列和中序遍歷序列,請根據這兩個序列重建一棵二叉樹。(假設輸入的後序遍歷和中序遍歷的結果都不包含重複的數字)

  • 2.思路

      同前面的重建二叉樹的思路相似,只不過後序遍歷的根結點在序列的末尾,然後前面是所有右子樹的結點,再前面是所有左子樹的結點。

  • 3.C++實現

class Solution {
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if(inorder.size()==0)return nullptr;
        if(inorder.size()!=postorder.size())return nullptr;
        return create(inorder,postorder,0,inorder.size()-1,0,postorder.size()-1);
    }
    TreeNode* create(vector<int>& inorder,vector<int>& postorder,int is,int ie,int ps,int pe){
        if(ps>pe)return nullptr;
        TreeNode* node = new TreeNode(postorder[pe]);
        int pos = 0;
        for(int i=is;i<=ie;i++){
            if(inorder[i]==node->val){
                pos = i;
                break;
            }
        }
        int rightLen = ie - pos;
        node->right = create(inorder,postorder,pos+1,ie,pe-rightLen,pe-1);
        node->left = create(inorder,postorder,is,pos-1,ps,pe-rightLen-1);
        return node;
    }
};