中序序列
思路
易知:
前序遍历顺序为:根、左子树、右子树;
中序遍历顺序为:左子树、根、右子树;
后序遍历顺序为:左子树、右子树、根;
由前序遍历可知,整棵树的根节点是 。
对于样例:
3 2 1 4 5
1 5 4 2 3
结合前序、后序遍历可得整棵树的结构:
得到规律:
在先序遍历序列中,根节点之后是左儿子结点;在后序遍历序列中,根节点之前是右儿子结点。
枚举先序遍历中的节点,结合其在后序遍历中的位置,判断其子树所包含节点范围,递归求解即可。
Code
class Solution{ private: vector<int> ans; vector<int> pre, suf; struct node { int val; node *lson = NULL, *rson = NULL; }; public: node *build(int l1, int r1, int l2, int r2) { if (l1 > r1) return nullptr; node *cur = new node(); cur->val = pre[l1]; if (l1 == r1) return cur; int pos; for (int i = l2; i <= r2; ++i) { if (pre[l1 + 1] == suf[i]) { pos = i; break; } } cur->lson = build(l1 + 1, pos - l2 + l1 + 1, l2, pos); cur->rson = build(pos - l2 + l1 + 2, r1, pos + 1, r2 - 1); return cur; } void dfs(node *cur) { if (cur == NULL) return ; dfs(cur->lson); ans.push_back(cur->val); dfs(cur->rson); } vector<int> solve(int n, vector<int> npre, vector<int> nsuf) { pre.push_back(0); suf.push_back(0); for (int i = 0; i < n; ++i) { pre.push_back(npre[i]); suf.push_back(nsuf[i]); } node *root = build(1, n, 1, n); dfs(root); return ans; } };
优化
在上述思路的基础上,去掉建树过程,可直接在数组上递归求解。
Code
class Solution { public: /** * 返回所求中序序列 * @param n int整型 二叉树节点数量 * @param pre int整型vector 前序序列 * @param suf int整型vector 后序序列 * @return int整型vector */ vector<int>in; void build(int pl, int pr, int sl, int sr, vector<int>& pre, vector<int>& post, int l=0,int r=0) { if (pl > pr || sl > sr) return; int i; for (i = sr - 1; i >= sl && post[i] != pre[pl + 1]; i--); int left = i - sl + 1; in[l + left] = pre[pl]; build(pl + 1, pl + left, sl, i, pre, post,l); build(pl + left + 1, pr, i + 1, sr - 1, pre,post, l+left+1); } vector<int> solve(int n, vector<int>& pre, vector<int>& suf) { // write code here in = vector<int>(n); build(0, n - 1, 0, n - 1, pre, suf); return in; } };