代码随想录算法训练营 Day 18 | 513.找树左下角的值,112.路径总和,106.从中序与后序遍历序列构造二叉树

513.找树左下角的值

讲解链接:代码随想录-513.找树左下角的值

这道题注意一个点,最后一行最左侧的值,而不是最深一行左节点的值。

递归法

代码随想录中用到了全局变量,说实话,工作几年了,全局变量用起来还是比较慎重的,习惯上能不用就不用吧。所以我这里稍微该了一下,

  1. 确定参数和返回类型:返回一个长度为 2 的 int 数组,用来当前叶子节点的深度和最左侧的值。参数就是父节点的深度。
  2. 确定递归终止条件:当到叶子结点的时候,就进行返回。
  3. 确定单层递归逻辑:如果子节点不为空,就进行遍历,然后判断左右子节点谁更深,返回更深的那个结果。
public int findBottomLeftValue(TreeNode root) {
    return traversal(root, 0)[1];
}

int[] traversal(TreeNode node, int depth) {
    int[] result = new int[]{depth, node.val};
    // 如果是叶子结点,直接返回当前节点的深度和值
    if (node.left == null && node.right == null) return result;

    int[] leftInt = result;
    int[] rightInt = result;
    depth++;
    if (node.left != null) {
        leftInt = traversal(node.left, depth);
    }
    if (node.right != null) {
        rightInt = traversal(node.right, depth);
    }
    // 如果左子节最大深度点大于等于右子节点最大深度,就返回左字节点数组
    if (leftInt[0] >= rightInt[0]) {
        result = leftInt;
    } else {
        result = rightInt;
    }
    return result;
}

层序遍历

112.路径总和

讲解链接:代码随想录-112.路径总和

  1. 确定参数和返回类型:可以每次递归,用目标值减去当前节点值,如果是叶子节点,减去后的结果为 0,则说明存在,直接返回 true 即可。
  2. 确定递归终止条件:当到叶子结点的时候,就进行判断返回。其余情况返回 false。
  3. 确定单层递归逻辑:当底层返回 true 的时候,可以不用继续递归,继续返回 true 即可。

代码可以做精简,我这里为了提现思考过程,代码有点冗余。

public boolean hasPathSum(TreeNode root, int targetSum) {
    // 为空直接 false
    if (root == null) return false;
    // 目标值减去当前节点值,
    targetSum -= root.val;
    // 是叶子节点
    if (root.left == null && root.right == null) {
        if (targetSum == 0) { // 目标值等于0,就说明存在路径,返回true
            return true;
        } else { // 否则返回false
            return false;
        }
    }
    if (root.left != null) {
        // 如果存在就直接返回了,不用再递归右节点了
        if (hasPathSum(root.left, targetSum)) {
            return true;
        }
    }
    if (root.right != null) {
        // 同理
        if (hasPathSum(root.right, targetSum)) {
            return true;
        }
    }
    return false;
}

暴力破解

我这里还有另一个思路,就是效率和空间会浪费,算是暴力破解吧。创建一个结果集Set,把所有根节点到叶子结点的路径和存在里面,最后判断集合中是否存在目标值即可。

public boolean hasPathSum(TreeNode root, int targetSum) {
    if (root == null) return false;
    Set<Integer> sumSet = new HashSet<>();
    getSumSet(root, 0, sumSet);
    return sumSet.contains(targetSum);
}

void getSumSet(TreeNode node, int sum, Set<Integer> sumSet) {
    if (node == null) {
        sumSet.add(sum);
        return;
    }
    sum += node.val;
    getSumSet(node.left, sum, sumSet);
    getSumSet(node.right, sum, sumSet);
}

106.从中序与后序遍历序列构造二叉树

讲解链接:代码随想录-106.从中序与后序遍历序列构造二叉树

最好看视频理解,我自己也是琢磨着写的。

public TreeNode buildTree(int[] inorder, int[] postorder) {
    if (postorder == null || postorder.length == 0) {
        return null;
    }
    if (postorder.length == 1) return new TreeNode(postorder[0]);
    int nodeVal = postorder[postorder.length - 1];
    int index = 0;
    for (int i = 0; i < inorder.length; i++) {
        if (inorder[i] == nodeVal) {
            index = i;
            break;
        }
    }
    int[] leftInorder = arrSplit(inorder, 0, index);
    int[] rightInorder = arrSplit(inorder, index + 1, inorder.length);
    int[] leftPostorder = arrSplit(postorder, 0, leftInorder.length);
    int[] rightPostorder = arrSplit(postorder, leftInorder.length, leftInorder.length + rightInorder.length);
    TreeNode node = new TreeNode();
    node.left = buildTree(leftInorder, leftPostorder);
    node.right = buildTree(rightInorder, rightPostorder);
    node.val = nodeVal;

    return node;
}

public int[] arrSplit(int[] arrays, int startIndex, int endIndex) {
    if (arrays.length <= startIndex)
        return new int[0];
    int[] result = new int[endIndex - startIndex];
    for (int i = 0; i < result.length; i++) {
        result[i] = arrays[startIndex + i];
    }
    return result;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值