可以在父节点判断一下,如果左子树不为null,并且左子树没有左右子树,说明这是个左叶子节点。
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root == null) return 0;
int LV = sumOfLeftLeaves(root.left);
int RV = sumOfLeftLeaves(root.right);
int t = 0;
if (root.left != null && root.left.left == null && root.left.right == null) {
t = root.left.val;
}
return t+LV+RV;
}
}
一开始我用的递归,用布尔值传值,于是我写了如下代码。
class Solution {
static int ans = 0;
public int sumOfLeftLeaves(TreeNode root) {
preOrder(root, false);
return ans;
}
static void preOrder(TreeNode root, boolean isLeft){
if(root == null) return;
if(isLeft && root.left == null && root.right == null){
ans += root.val;
return;
}
preOrder(root.left, true);
preOrder(root.right, false);
}
}
这个测试用例竟然会输出24。
想了一天,晚上突然明白了,测试用例1答案是24,测试用例2答案应该是0,但是为什么是24呢?因为测试用例2答案在第一个基础上,也就是24+0 = 24
而我的ans变量是static的,也就是所有实例共享的,把代码改成下面这样就过了。
class Solution {
int ans = 0;
public int sumOfLeftLeaves(TreeNode root) {
preOrder(root, false);
return ans;
}
void preOrder(TreeNode root, boolean isLeft){
if(root == null) return;
if(isLeft && root.left == null && root.right == null){
ans += root.val;
return;
}
preOrder(root.left, true);
preOrder(root.right, false);
}
}
这个题应该挺好想的,左下角是最底层,最左边的值,用层序遍历就很好实现,遍历到最后一层记录第一个值就是答案。
class Solution {
public int findBottomLeftValue(TreeNode root) {
//层序遍历 最后一层 第一个节点
LinkedList q = new LinkedList<>();
int ans = 0;
if(root == null) return 0;
q.offer(root);
while(!q.isEmpty()){
int len = q.size();
for(int i = 0; i < len; i++){
TreeNode t = q.poll();
if(i == 0) ans = t.val;
if(t.left != null){
q.offer(t.left);
}
if(t.right != null){
q.offer(t.right);
}
}
}
return ans;
}
}
跟昨天的输出路径题一个套路(257. 二叉树的所有路径),核心还是判断是不是叶子节点,当左右子树都为null并且传的值等于target的时候说明找到了,为了保证不出现空指针异常,每次递归都要判断一下。
class Solution {
boolean f = false;
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root == null) return f;
preOrder(root, targetSum, 0);
return f;
}
void preOrder(TreeNode root, int target, int n){
if(f) return;
n += root.val;
if(root.left == null && root.right == null && n == target){
f = true;
return;
}
if(root != null && root.left != null) preOrder(root.left, target, n);
if(root != null && root.right != null) preOrder(root.right, target, n);
}
}
跟昨天做的根据前序中序构造树一个思路,代码都很像,for循环找到最大值,然后根据最大值位置划分左右子树,递归地遍历左右子树,左子树范围0——index,右子树范围index+1——length。
但是要注意判断一下index是否是边界,也就是为0或length-1的时候,左子树或右子树直接就是null了。
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
int r = -1, index = 0;
for(int i = 0; i < nums.length; i++){
if(nums[i] > r){
r = nums[i];
index = i;
}
}
TreeNode root = new TreeNode(r);
if(index == 0) root.left = null;
else root.left = constructMaximumBinaryTree(Arrays.copyOfRange(nums, 0, index));
if(index == nums.length-1) root.right = null;
else root.right = constructMaximumBinaryTree(Arrays.copyOfRange(nums, index+1, nums.length));
return root;
}
}
核心在于如何同步遍历两个二叉树。
每次把结果都加到root1这棵树上就好,节省空间。
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;
}
}