513.找树左下角的值
讲解链接:代码随想录-513.找树左下角的值
这道题注意一个点,最后一行最左侧的值,而不是最深一行左节点的值。
递归法
代码随想录中用到了全局变量,说实话,工作几年了,全局变量用起来还是比较慎重的,习惯上能不用就不用吧。所以我这里稍微该了一下,
- 确定参数和返回类型:返回一个长度为 2 的 int 数组,用来当前叶子节点的深度和最左侧的值。参数就是父节点的深度。
- 确定递归终止条件:当到叶子结点的时候,就进行返回。
- 确定单层递归逻辑:如果子节点不为空,就进行遍历,然后判断左右子节点谁更深,返回更深的那个结果。
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.路径总和
- 确定参数和返回类型:可以每次递归,用目标值减去当前节点值,如果是叶子节点,减去后的结果为 0,则说明存在,直接返回 true 即可。
- 确定递归终止条件:当到叶子结点的时候,就进行判断返回。其余情况返回 false。
- 确定单层递归逻辑:当底层返回 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;
}