从【前中序遍历序列构造二叉树】中体会分治思想
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)是右子树根的位置。

浙公网安备 33010602011771号