LintCode-劍指Offer-(73)前序遍歷和中序遍歷樹構造二叉樹

class Solution {
    /**'
    * '
    *@param preorder : A list of integers that preorder traversal of a tree
    *@param inorder : A list of integers that inorder traversal of a tree
    *@return : Root of a tree
    */
public:
    //獲取一個元素在vector中的下標
    int getLoc(vector<int >& ino, int ele){
        for ( int i = 0; i < ino.size( ); i++ ){
            if ( ino[i] == ele ){
                return i;
            }
        }
        return -1;
    }
    //是否在左邊子樹中
    bool IsInChildLeftTree(int ele, int s, int e, vector<int> v){
        for ( int i = s; i < e; i++ ){
            if ( ele == v[i] )
                return true;
        }
        return false;
    }
public:

    //找到右子樹的根節點
    //s:中序遍歷中左子樹的起點
    //incurpos:當前子樹根節點在中序遍歷的位置,是查找的終點
    //precurpos:當前子樹根節點在前序遍歷的位置 ,也是左子樹的終點
    int findRightRoot(vector<int> pre, vector<int> ino, int s, int precurpos, int incurpos)
    {
        int i = precurpos + 1; //當前根的起點,是在前序遍歷中的
        while ( i < pre.size( ) && IsInChildLeftTree(pre[i], s, incurpos, ino) == true ){  //如果處於左子樹中,下標增加
            i++;
        }
        if ( i >= pre.size( ) )return -1;
        return i;
    }
    //s:子樹起點
    //e:子樹終點,這兩個都是指在中序遍歷中的位置
    //precurpos:當前子樹根節點的在前序遍歷中的位置
    //incurpos:當前子樹根節點在中序遍歷的位置
    //node:傳入的根節點
    TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {
        // write your code here
        TreeNode* root = NULL;
        if ( preorder.size( ) == 0 )
            return NULL;
        buildTree(preorder, inorder, 0, preorder.size( ), 0, getLoc(inorder, preorder[0]), root);
        return root;
    }

     //s,e指定了區間長度
    //precurpos:當前根在前序遍歷中的位置
    //incurpos:當前根在中序遍歷中的位置
    void buildTree(vector<int> &preorder, vector<int> &inorder, int s, int e, int precurpos, int incurpos, TreeNode*& node) {
        static int* inblocked = new int[preorder.size( )];  //保存當前已經構造完畢的節點
        if ( s >= e || precurpos > preorder.size( ) || incurpos > preorder.size( ) || e > preorder.size( ) ){
            node = NULL;
            return;
        }
        node = new TreeNode(preorder[precurpos]);//當前節點已經構造,不用再次構造
        int currentblockloc = getLoc(inorder, preorder[precurpos]);
        inblocked[currentblockloc] = 1;//所以不用再次構造,blocked=1
        //cout << "constructing node:" << node->val << endl;   
        //從先序遍歷中找到右邊子節點
        int tmprightcur = findRightRoot(preorder, inorder, s, precurpos, incurpos);
        int ttt; //找到當前節點在中序遍歷中的位置,這個位置可以將中序遍歷的序列分爲左邊和右邊
        ttt= getLoc(inorder, preorder[precurpos]);
        //cout << "start from:" << s << "end with:" << ttt << endl;
        //如果當前左邊已經到邊界,或者已經有值,那麼左邊不用處理
        if ( !( currentblockloc < 0 || (currentblockloc>0&& inblocked[currentblockloc - 1] == 1 ) ) && precurpos + 1<preorder.size() )
            buildTree(preorder, inorder, s, ttt, precurpos + 1, getLoc(inorder, preorder[precurpos + 1]), node->left);
        //cout << "start from:" << ttt << "end with:" << tmprightcur << endl;
        //如果當前右邊已經到了邊界,或者已經有值,那麼右邊不用處理
        if ( !( currentblockloc >= preorder.size() || (currentblockloc<preorder.size()-1&& inblocked[currentblockloc + 1] == 1)&&tmprightcur!=-1 )
            && tmprightcur<preorder.size() )
            buildTree(preorder, inorder, ttt,e, tmprightcur,getLoc(inorder,preorder[tmprightcur]), node->right);
    }
    void DisplayTree(TreeNode* root){
        if ( root == NULL )
            return;
        cout << root->val << endl;
        DisplayTree(root->left);
        DisplayTree(root->right);
    }
};
發佈了53 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章