劍指Offer 面試題07. 重建二叉樹

解題思路

利用遞歸分治法重新建立二叉樹:
首先,我們先找規律。給定一個二叉樹的前序遍歷和中序遍歷是可以唯一確定一顆二叉樹的,怎麼建呢?
先序遍歷,每次都首先遍歷根節點,那麼好了,每一次我們在先序序列中的元素都是某子樹的根節點,整個先序序列的第一個元素就是整個二叉樹的根元素

既然根元素確定了,就需要知道根元素的左子樹和右子樹都有哪些,怎麼確定呢?就要去中序序列中找,如下如所示:
在這裏插入圖片描述
當我們的根節點確定了是3之後,要去中序遍歷中找以3爲根節點的左右子樹,中序遍歷的順序是:左子樹、根、右子樹,所以當我們在中序序列中找到3之後,自然左面的都是左子樹,右面的都是右子樹,這樣一直遞歸重建,就得到我們想要的結果了。

源代碼:

class Solution {
public:
    TreeNode* helper(vector<int>& preorder,int p_b,int p_e,vector<int>& inorder, int i_b,int i_e){
        //初始化當前的根節點
        TreeNode *root = new TreeNode(preorder[p_b]);
        root->left = NULL;
        root->right = NULL;
        //這裏是要在中序序列中找到根節點
        int i = i_b;
        while(i < i_e && inorder[i] != preorder[p_b]) i++;
        //這裏要記錄左右子樹長度,如果某一面沒有,就沒必要再去遞歸建立
        int i_l_len = i-i_b, i_r_len=i_e-i;
        if(i_l_len > 0){
            /* 
			每次建立,中序序列的起點和終點以及前序序列的起點和終點
			都不太一樣。
			前序序列中,下一個元素就是我們左子樹重建的根節點,而到哪裏結束呢?
			就是起點加上左子樹的個數。
			右子樹同理,前序序列中,左子樹起點加上左孩子個數加1,
			就是右子樹的新起點,而原來的前序終點就是新終點;
			中序遍歷就很好確定了,以當前根節點索引爲界限(也就是i)
			左子樹就是原中序起點到i-1,
			右子樹就是i+1到原中序終點
            **/
            root->left = helper(preorder,p_b+1,p_b+i_l_len,inorder,i_b,i-1);
        }
        if(i_r_len > 0){
            root->right = helper(preorder,p_b+i_l_len+1,p_e,inorder,i+1,i_e);
        }
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(preorder.size() <= 0 || inorder.size() <= 0) return NULL;
        return helper(preorder,0,preorder.size()-1,inorder,0,inorder.size()-1);
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章