从【前中序遍历序列构造二叉树】中体会分治思想

LeetCode 105.从前序与中序遍历序列构造二叉树

class Solution {
public:

int n;
unordered_map <int ,int > mapp; //key是值,val是在inorder[]中的位置(下标)

TreeNode* dfs(int rt,int l,int r,vector <int > &preorder) //分别代表当前根在preorder[]的位置,和要搜索的inorder[]中的左右区间
{
    if(l > r) return nullptr;

    int pos = mapp[preorder[rt]];
    
    TreeNode* root = new TreeNode(preorder[rt]); //创建该点

    root->left = dfs(rt + 1,l,pos - 1,preorder);
    root->right = dfs(rt + 1 + pos - l,pos + 1,r,preorder);

    return root;
}

TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
{
    n = preorder.size();

    for(int i=0;i<n;i++)
       mapp[inorder[i]] = i;

    return dfs(0,0,n-1,preorder);
}
};

中序遍历将某节点和它的左右子树分开,前序遍历很容易得到根节点。因此我们很容易想到这是一道分治题。

分治题的破题关键是,不仅要找出与原问题没有冲突的子问题,更要找到子问题合并回原问题的条件。

 

如本题,我们在中序遍历里找到当前节点的左右子树区间,但是不会写递归到子问题的状态是不行的。

绞尽脑汁后发现,当前节点 preorder[rt] 和左右子树的关系:

    1.前序遍历中该节点的下一个(rt + 1)便是左子树的根的位置;

    2.中序遍历数组中该节点的位置(pos)和当前递归L的差值+1(pos - L + 1)就是左子树的长度,前序遍历中,rt后若干个是左子树节点,剩下的是右子树节点,因此上式 + rt(pos - L + 1 + rt)是右子树根的位置。

posted @ 2021-11-05 19:37  killerboom  阅读(39)  评论(0)    收藏  举报