代码随想录算法训练营 Day 17 | 110.平衡二叉树,257.二叉树的所有路径,404.左叶子之和

110.平衡二叉树

讲解链接:代码随想录-110.平衡二叉树

这里求的是高度,所以使用后序遍历。节点获取左右子节点的最大高度,然后相减的差绝对值大于 1,就说明不是平衡二叉树了。

解题代码:

public boolean isBalanced(TreeNode root) {
    return getHeight(root) != -1;
}

private int getHeight(TreeNode root) {
    if (root == null) {
        return 0;
    }
    int leftHeight = getHeight(root.left);
    if (leftHeight == -1) {
        return -1;
    }
    int rightHeight = getHeight(root.right);
    if (rightHeight == -1) {
        return -1;
    }
    // 左右子树高度差大于1,return -1表示已经不是平衡树了
    if (Math.abs(leftHeight - rightHeight) > 1) {
        return -1;
    }
    return Math.max(leftHeight, rightHeight) + 1;
}

257.二叉树的所有路径

讲解链接:代码随想录-257.二叉树的所有路径

使用前序遍历,

  1. 确定递归方法参数和返回值:参数需要传入父级的路径,同时还有一个结果集。
  2. 确定递归终止条件:当节点是叶子节点的时候,就可以返回了。把父级路径加上自己,添加到结果集中就可以了。
  3. 确定单层递归逻辑:这里需要用到回溯,针对参数父级的路径,如果不回溯的话,节点的左子节点路径遍历完了,不是会继续添加右子节点路径,结果就错误了。

解题代码:

public List<String> binaryTreePaths(TreeNode root) {
    List<String> result = new ArrayList<>();
    if (root == null) return result;
    List<Integer> paths = new ArrayList<>();
    traversal(root, paths, result);
    return result;
}
void traversal(TreeNode node, List<Integer> paths, List<String> result) {
    paths.add(node.val);
    if (node.left == null && node.right == null) {
        StringBuilder tempPath = new StringBuilder();
        for (int i = 0; i < paths.size(); i++) {
            tempPath.append(paths.get(i));
            if (i != paths.size() - 1) {
                tempPath.append("->");
            }
        }
        result.add(tempPath.toString());
        return;
    }
    if (node.left != null) {
        traversal(node.left, paths, result);
        paths.remove(paths.size() - 1);
    }
    if (node.right != null) {
        traversal(node.right, paths, result);
        paths.remove(paths.size() - 1);
    }
}

404.左叶子之和

讲解链接:代码随想录-404.左叶子之和

递归两种思路,

  1. 在叶子结点的父节点就判断子节点是否是坐叶子结点,如果是就返回左叶子结点的值,否则返回 0。
  2. 还有一个是递归入参多加一个参数,用来告诉子节点自己是不是左子节点,如果是叶子结点同时也是左子节点,那么就返回节点值。

递归法

父节点收集

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;
}

子节点判断返回

public int sumOfLeftLeaves(TreeNode root) {

    return traversal(root, false);
}
int traversal(TreeNode node, boolean left) {
    if (node == null) {
        return 0;
    }
    // 如果是叶子节点,同时是左子节点,返回节点值
    if (node.left == null && node.right == null && left) {
        return node.val;
    }
    int sum = 0;
    sum += traversal(node.left, true);
    sum += traversal(node.right, false);

    return sum;
}

迭代法

前序遍历

这里用的迭代方式前序遍历,思路和迭代法第一种一样,判断子节点是否是叶子结点,是的话就加上。

public int sumOfLeftLeaves(TreeNode root) {
    if (root == null) return 0;
    Stack<TreeNode> stack = new Stack<> ();
    stack.add(root);
    int result = 0;
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        if (node.left != null && node.left.left == null && node.left.right == null) {
            result += node.left.val;
        }
        if (node.right != null) stack.add(node.right);
        if (node.left != null) stack.add(node.left);
    }
    return result;
}

层序遍历

父节点判断

public int sumOfLeftLeaves(TreeNode root) {
    int sum = 0;
    if (root == null) return 0;
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);
    while (!queue.isEmpty()) {
        int size = queue.size();
        while (size-- > 0) {
            TreeNode node = queue.poll();
            if (node.left != null) { // 左节点不为空
                queue.offer(node.left);
                if (node.left.left == null && node.left.right == null) { // 左叶子节点
                    sum += node.left.val;
                }
            }
            if (node.right != null) queue.offer(node.right);
        }
    }
    return sum;
}

总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值