和二叉树的右视图比较像。
先左后右访问,使用全局变量maxDepth
,记录每个深度的第一个叶节点。
class Solution {
int maxDepth = -1;
int nodeLeft = 0;
public int findBottomLeftValue(TreeNode root) {
DFS(root, 0);
return nodeLeft;
}
public void DFS(TreeNode root, int depth) {
// 不处理root为null的情况,保证传入的root不等于null
if (root.left == null && root.right == null) {
if (depth > maxDepth) {
maxDepth = depth;
nodeLeft = root.val;
}
}
TreeNode left = root.left;
TreeNode right = root.right;
if (left != null) {
DFS(left, depth + 1);
}
if (right != null) {
DFS(right, depth + 1);
}
}
}
向下递归的过程中,targetSum
递减。
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) {
return false;
}
if (root.left == null && root.right == null) {
if (root.val == targetSum) {
return true;
}
else {
return false;
}
}
return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
}
}
做第二遍了,还是思路不顺畅,希望这次记住吧~
向下递归的过程中,targetSum
递减。
使用一个stack记录遍历时经过的路径,
有回溯:在DFS的过程中,先push进root,然后左子树、右子树遍历,再pop掉root。
向容器中加入新路径的过程:即发现符合要求的叶子节点时加入stack,但需要new一个新的对象。
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
class Solution {
List<List<Integer>> res = new LinkedList<List<Integer>>();
// 使用一个stack
Stack<Integer> stack = new Stack<>();
public List<List<Integer>> pathSum (TreeNode root, int targetSum) {
if (root == null) {
return res;
}
DFS(root, targetSum);
return res;
}
public void DFS (TreeNode root, int targetSum) {
// 保证传入的值不为null
// 向下递归的过程中,targetSum递减
stack.push(root.val);
if (root.left == null && root.right == null && targetSum == root.val) {
// 新建一个path对象,加入当前的path
res.add(new LinkedList<>(stack));
}
if (root.left != null) {
DFS(root.left, targetSum - root.val);
}
if (root.right != null) {
DFS(root.right, targetSum - root.val);
}
stack.pop();
return;
}
}
由前序遍历得根节点,由中序遍历得左子树和右子树的范围,然后递归。
public class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
// 前序遍历
// 中序遍历
return buildTree(preorder, inorder, 0, preorder.length - 1, 0, inorder.length - 1);
}
public TreeNode buildTree(int[] preorder, int[] inorder, int l1, int r1, int l2, int r2) {
// l1, r1代表preorder[l1, r1]
// l2, r2代表inorder[l2, r2]
if (l1 > r1) {
return null;
}
// 这棵树根节点的值
int rootVal = preorder[l1];
TreeNode root = new TreeNode(rootVal);
if (l1 == r1) {
return root;
}
// 找到根节点在中序遍历中的位置:
// 左:[l2, index - 1],index,右:[index + 1, r2]
int index = l2;
for (int i = l2; i <= r2; i++) {
if (inorder[i] == rootVal) {
index = i;
break;
}
}
int leftLength = index - l2;
int rightLength = r2 - index;
// 左子树在前序遍历中的位置: [l1 + 1, l1 + leftLength]
// 右子树在前序遍历中的位置 [r1 - rightLength + 1, r1]
root.left = buildTree(preorder, inorder, l1 + 1, l1 + leftLength, l2, index - 1);
root.right = buildTree(preorder, inorder, r1 - rightLength + 1, r1, index + 1, r2);
return root;
}
}