1. 程式人生 > >劍指offer------重建二叉樹

劍指offer------重建二叉樹

題目

輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。

思路

通常樹有如下幾種遍歷方式:

  • 前序遍歷:先訪問根結點,再訪問左子結點,最後訪問右子結點。
  • 中序遍歷:先訪問左子結點,再訪問根結點,最後訪問右子結點。
  • 後序遍歷:先訪問左子結點,再訪問右子結點,最後訪問根結點。

本題為前序遍歷和中序遍歷,最少需要兩種遍歷方式,才能重建二叉樹。

前序遍歷序列中,第一個數字總是樹的根結點的值。在中序遍歷序列中,根結點的值在序列的中間,左子樹的結點的值位於根結點的值的左邊,而右子樹的結點的值位於根結點的值的右邊。剩下的我們可以遞迴來實現,具體如圖:

劍指Offer(四):重建二叉樹

程式碼:

struct TreeNode
{
	int val;
	TreeNode *left;
	TreeNode *right;
}

class Solution
{
public:
	TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin)
	{
		if(pre.size()==0||vin.size()==0)
			return NULL;
			
		//依次是前序遍歷左子樹,前序遍歷右子樹,中序遍歷左子樹,中序遍歷右子樹
		vector<int> left_pre, right_pre, left_vin, right_vin;
		
        //前序遍歷第一個節點一定為根節點
		TreeNode* head = new TreeNode();
		head-val=pre[0];
		
		//找到中序遍歷的根節點
		int root = 0;
		
		//遍歷找到中序遍歷根節點索引值
		for(int i=0;i<pre.size();i++)
		{
			if(pre[0]==vin[i])
			{
				root=i;
				break;
			}
		}
		
		//利用中序遍歷的根節點,對二叉樹節點進行歸併
		for(int i=0;i<root;i++)
		{
			left_vin.push_back(vin[i]);
			left-pre.push_back(pre[i+1]);
		}
		
		for(int i=root+1;i<pre.size();i++)
		{
			right_vin.push_back(vin[i]);
			right_pre.push_back(pre[i]);
		}
		
		//遞迴,再對其進行上述所有步驟,即再區分子樹的左、右子子數,直到葉節點
        head->left = reConstructBinaryTree(left_pre, left_vin);
        head->right = reConstructBinaryTree(right_pre, right_vin);
        return head;
    }
};