树的生成与变形
1. 树的生成
1.1 根据遍历建树
106. Construct Binary Tree from Inorder and Postorder Traversal
Given inorder and postorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
For example, given
inorder = [9,3,15,20,7]
postorder = [9,15,7,20,3]
Return the following binary tree:
3
/ \
9 20
/ \
15 7
题目大意
给中序和后序遍历的两个数组,返回他们对应的二叉树。
解题思路
非递归: 用两个pointer从后向前遍历两个遍历数组,从右到左的建立树。
递归:已知后序遍历的最后一个值是根节点的值,找到中序遍历中根节点的位置,以此得到子树的边界:
- k 为根节点在中序遍历中的位置
- 左子树边界: 中序(instart, k - 1), 后序(poststart, poststart + (k - 1 - instart))
- 右子树边界: 中序(k + 1, inend), 后序(poststart + k - instart, postend - 1)
复杂度
非递归: TC: O(n) SC: O(n)
递归: TC: O(nlgn) SC: O(n)
//非递归解法
private int postIndex;
private int inIndex;
public TreeNode buildTree(int[] inorder, int[] postorder) {
postIndex = postorder.length - 1;
inIndex = inorder.length - 1;
return traverse(postorder, inorder, null);
}
private TreeNode traverse(int[] postorder, int[] inorder, TreeNode root){
if (postIndex < 0 || inIndex < 0 || (root != null && root.val == inorder[inIndex])) return null;
TreeNode cur = new TreeNode(postorder[postIndex--]);
cur.right = traverse(postorder, inorder, cur);
inIndex--;
cur.left = traverse(postorder, inorder, root);
return cur;
}
//递归解法
public TreeNode buildTree(int[] inorder, int[] postorder) {
int inStart = 0;
int inEnd = inorder.length - 1;
int postStart = 0;
int postEnd = postorder.length - 1;
return buildTree(inorder, inStart, inEnd, postorder, postStart, postEnd);
}
public TreeNode buildTree(int[] inorder, int inStart, int inEnd,
int[] postorder, int postStart, int postEnd) {
if (inStart > inEnd || postStart > postEnd)
return null;
int rootValue = postorder[postEnd];
TreeNode root = new TreeNode(rootValue);
int k = 0;
for (int i = 0; i < inorder.length; i++) {
if (inorder[i] == rootValue) {
k = i;
break;
}
}
root.left = buildTree(inorder, inStart, k - 1, postorder, postStart,postStart + k - (inStart + 1));
// Becuase k is not the length, it it need to -(inStart+1) to get the length
root.right = buildTree(inorder, k + 1, inEnd, postorder, postStart + k- inStart, postEnd - 1);
// postStart+k-inStart = postStart+k-(inStart+1) +1
return root;
}
105. Construct Binary Tree from Preorder and Inorder Traversal
Given preorder and inorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
For example, given
preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
Return the following binary tree:
3
/ \
9 20
/ \
15 7
题目大意
给中序和先序遍历的两个数组,返回他们对应的二叉树。
解题思路
非递归: 用两个pointer从前向后遍历两个遍历数组,从左到右的建立树。
递归:已知后序遍历的最后一个值是根节点的值,找到中序遍历中根节点的位置,以此得到子树的边界:
- k 为根节点在中序遍历中的位置
- 左子树边界: 中序(instart, k - 1), 先序(prestart + 1, poststart + (k - instart))
- 右子树边界: 中序(k + 1, inend), 先序(prestart + k - instart + 1, preend)
复杂度
非递归: TC: O(n) SC: O(n)
递归: TC: O(nlgn) SC: O(n)
//非递归解法
private int preIndex;
private int inIndex;
public TreeNode buildTree(int[] preorder, int[] inorder) {
preIndex = 0;
inIndex = 0;
// peroder build inorder check
return traverse(preorder, inorder, null);
}
private TreeNode traverse(int[] preorder, int[] inorder, TreeNode root){
if ((root != null && root.val == inorder[inIndex]) || preIndex >= preorder.length) return null;
TreeNode cur = new TreeNode(preorder[preIndex++]);
cur.left = traverse(preorder, inorder, cur);
inIndex++;
cur.right = traverse(preorder, inorder, root);
return cur;
}
//递归解法
public TreeNode b