一、左叶子之和
要想判断判断一个节点是不是左子叶,要通过其父节点判断左孩子是不是左子叶。
1. 确定递归的参数和返回值。传入根节点,返回左右子树的左叶子之和。
2.终止条件。当为null时,返回0。
3. 确定单层递归的逻辑。通过后序遍历,求左右子树的左叶子节点之和。当碰到左叶子节点时,midvalue就是左叶子节点的值,否则当前节点为右叶子或者树节点,midvalue就是0,返回左右子树的左叶子节点之和。
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if (root == null) return 0;
int leftValue = sumOfLeftLeaves(root.left);
int rightValue = sumOfLeftLeaves(root.right);
int midValue = 0;
if (root.left != null && root.left.left == null && root.left.right == null) {
midValue = root.left.val;
}
int sum = midValue + leftValue + rightValue;
return sum;
}
}
二、树左下角的值
很方便,直接使用层序遍历,用一个变量循环记录每层第一个节点的值。当遍历结束后,保存的就是左下角的值。
class Solution {
public int findBottomLeftValue(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int res = 0;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode poll = queue.poll();
if (i == 0) {
res = poll.val;
}
if (poll.left != null) {
queue.offer(poll.left);
}
if (poll.right != null) {
queue.offer(poll.right);
}
}
}
return res;
}
}
三、路径总和
class solution {
public boolean haspathsum(treenode root, int targetsum) {
if (root == null) return false; // 为空退出
// 叶子节点判断是否符合
if (root.left == null && root.right == null) return root.val == targetsum;
// 求两侧分支的路径和
return haspathsum(root.left, targetsum - root.val) || haspathsum(root.right, targetsum - root.val);
}
}
四、从中序与后序遍历序列构造二叉树
分为如下几步:
第一步:如果数组大小为零的话,说明是空节点了
第二步:如果不为空,那么取后序数组最后一个元素作为节点元素
第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
第四步:切割中序数组,切成中序左数组和中序右数组
第五步:切割后序数组,切成后序左数组和后序右数组
第六步:将中序左数组和后序左数组传给左子树节点,将中序右数组和后序右数组传给右子树节点。
在一开始可以先用map记录下中序数组的值和对应的索引,这样就可以找到后序数组最后一个元素在中序数组的位置了。
在递归的参数中不需要每次传入新数组,只需要传入相同的数组和切割后数组的左右索引就可以了。
class Solution {
Map<Integer, Integer> map;
public TreeNode buildTree(int[] inorder, int[] postorder) {
map = new HashMap<>();
for (int i = 0; i < inorder.length; i++) map.put(inorder[i], i);
return findNode(inorder, 0, inorder.length, postorder,0, postorder.length);
}
public TreeNode findNode(int[] inorder, int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd) {
if (inBegin >= inEnd || postBegin >= postEnd) return null;
int rootIdx = map.get(postorder[postEnd - 1]);
TreeNode root = new TreeNode(inorder[rootIdx]);
int leftLen = rootIdx - inBegin;
root.left = findNode(inorder, inBegin, rootIdx, postorder, postBegin, postBegin + leftLen);
root.right = findNode(inorder, rootIdx + 1, inEnd, postorder, postBegin + leftLen, postEnd - 1);
return root;
}
}
五、最大二叉树
这道题对最大二叉树做出的定义就是在把我们往递归的路子上引。
和上一题有些类似,在递归的参数中不需要每次传入新数组,只需要传入相同的数组和切割后数组的左右索引就可以了。
这些构造二叉树的题都应该通过前序遍历来解决。
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
return recursion(nums, 0, nums.length);
}
public TreeNode recursion(int[] nums, int left, int right) {
if (right <= left) return null;
int maxValueIdx = left;
for (int i = left + 1; i < right; i++)
if (nums[i] > nums[maxValueIdx])
maxValueIdx = i;
TreeNode root = new TreeNode(nums[maxValueIdx]);
root.left = recursion(nums, left, maxValueIdx);
root.right = recursion(nums, maxValueIdx + 1, right);
return root;
}
}
六、合并二叉树
终止条件:如果root1为null,就返回root2,root2有值最好,合并之后就是root2,如果为null也无所谓,合并之后就是null。同理,如果root2为null,就返回root1。
单层递归逻辑:把root2的值加在root1上,实际上就是给root1加上了root2。
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if (root1 == null) return root2;
if (root2 == null) return root1;
root1.val += root2.val;
root1.left = mergeTrees(root1.left, root2.left);
root1.right = mergeTrees(root1.right, root2.right);
return root1;
}
}