124. 二叉树中的最大路径和
链接:二叉树中的最大路径和
解题思路:
最大路径 = 该节点的值 + 左节点的最大贡献值 + 右节点的最大贡献值,即:
ans = Math.max(ans, left + right + root.val);
每个节点的最大贡献值 = 该节点的值 + max(左节点的最大贡献值, 右节点的最大贡献值),即:
root.val + Math.max(left, right);
最后才加上该节点的值,故采用后序遍历。
代码:
class Solution {
int ans = Integer.MIN_VALUE;
public int maxGain(TreeNode root) {
if(root == null) {
return 0;
}else {
int left = Math.max(0, maxGain(root.left));
int right = Math.max(0, maxGain(root.right));
ans = Math.max(ans, left + right + root.val);
return root.val + Math.max(left, right);
}
}
public int maxPathSum(TreeNode root) {
maxGain(root);
return ans;
}
}
105. 从前序与中序遍历序列构造二叉树
链接:从前序与中序遍历序列构造二叉树
解题思路:
根据前序遍历可以知道根节点,再根据根节点在中序遍历中的位置可以得到左子树与右子树。
前序遍历:[根节点,左子树,右子树],其中左右子树皆是前序遍历的结果
中序遍历:[左子树,根节点,右子树],其中左右子树皆是中序遍历的结果
如上,根据中序遍历中根节点的位置与左子树的边界,可以得到左子树数目的大小,再通过左子树数目的大小推出前序遍历中属于左子树的部分;中序遍历中右子树的部分所以可以采用递归不断构建左右子树。
最初时中序遍历中左子树边界为0
,右子树边界为inorder.length-1
;前序遍历中左子树边界为0
,右子树边界为preorder.length-1
。即build(preorder, inorder, 0, preorder.length-1, 0, inorder.length-1);
中序遍历中:
左子树节点数目size = 根节点位置index - 左子树边界preLeft
左子树:[左子树边界inLeft, 根节点位置index -1]
右子树:[根节点位置index +1, 右子树边界inRight]
前序遍历中:
原左边界preLeft即是根节点,+1则是左子树开始部分
左子树:[左子树边界preLeft+ 1, 左子树边界preLeft + 左子树节点数目size]
右子树:[左子树边界preLeft + 左子树节点数目size + 1, 右子树边界preRight]
即:
root.left = build(preorder, inorder, preleft+1, preleft+size, inleft, index-1);
root.right = build(preorder, inorder, preleft+size+1, preright, index+1, inright);
另外,采用hashmap可以快速获取中序遍历中节点在中序遍历中的位置
代码:
class Solution {
private HashMap<Integer, Integer> map;
public TreeNode build(int[] preorder, int[] inorder, int preleft, int preright, int inleft, int inright) {
if (preleft > preright) {
return null;
}
int index = map.get(preorder[preleft]);
int size = index - inleft;
TreeNode root = new TreeNode(preorder[preleft]);
root.left = build(preorder, inorder, preleft+1, preleft+size, inleft, index-1);
root.right = build(preorder, inorder, preleft+size+1, preright, index+1, inright);
return root;
}
public TreeNode buildTree(int[] preorder, int[] inorder) {
map = new HashMap<Integer, Integer>();
for(int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
}
return build(preorder, inorder, 0, preorder.length-1, 0, inorder.length-1);
}
}
99. 恢复二叉搜索树
链接:恢复二叉搜索树
解题思路:
采用中序遍历,则得到的是一个递增的数列。
设x
和y
两个节点变量为null,每次root
与前一个节点pre
进行比较大小:倘若root.val
> pre.root
,则x = root,如果 y != null,y = pre(y值只需要记录一次)。
最后再将x的值与y的值进行交换
代码:
class Solution {
TreeNode x = null;
TreeNode y = null;
TreeNode pre = new TreeNode(Integer.MIN_VALUE);
public void recoverTree(TreeNode root) {
recover(root);
if(x != null && y != null) {
int temp = x.val;
x.val = y.val;
y.val = temp;
}
}
void recover(TreeNode root) {
if(root == null) return;
recover(root.left);
if(root.val < pre.val) {
x = root;
if(y == null) {
y = pre;
}
}
pre = root;
recover(root.right);
}
}