一、二叉树的所有路径(递归(回溯))
整体思路:对二叉树进行前序递归遍历。(中左右,先输出,然后递归左子节点和右子节点);
1.确定递归函数的返回值为void 参数为TreeNode node,List<Integer> paths(单条路径),List<String> lists(路径的集合)
2.递归函数的终止条件:(root.left==null&&root.right==null)return ;
3.处理递归逻辑:
3.1 当遇到左节点不空
if(node.left!=null){
traversal(node.left,lists,paths);
paths.remove(paths.size()-1);
}
左节点不为空就继续向下递归,但是还要加回溯。
1->2->5 在5的左右子节点都为空的时候,然后把路径添加到lists中。然后回到函数中就要回到1->2,在2这个结点中,就要回到1。
3.2、遇到右结点为空 相同的逻辑
3.3 当左右节点都为空的时候,说明到了叶子节点。向下已经没有路了。在这种情况下要把paths单条路径中的结点都输出,并且使用StringBuilder拼接->;
代码:
public List<String> binaryTreePaths(TreeNode root) {
List<String> list = new ArrayList<>();
if (root == null)
return list;
List<Integer> paths = new ArrayList<>();
traversal(root, list, paths);
return list;
}
public void traversal(TreeNode node, List<String> lists, List<Integer> paths) {
// 前序遍历 中(将结点的值添加到paths中)
paths.add(node.val);
// 前序遍历 左
if (node.left != null) {
traversal(node.left, lists, paths);
paths.remove(paths.size() - 1);
}
//前序遍历 右
if (node.right != null) {
traversal(node.right, lists, paths);
paths.remove(paths.size() - 1);
}
// 如果遇到子节点,就把路径直接输出
if (node.left == null && node.right == null) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < paths.size() - 1; i++) {
sb.append(paths.get(i)).append("->");
}
sb.append(paths.get(paths.size() - 1));
lists.add(sb.toString());
return;
}
}
二、左叶子之和(递归法)
1.返回值 :int 参数:TreeNode node
2.终止条件 (node==null) (node.left==null&&node.right==null) return 0;
3.递归逻辑:后序遍历(左右中)
左:递归左子树,得到左子树中左叶子结点的值
右:递归右子树,得到右子树中左叶子节点的值
中:合二为一
在进行左递归的时候,如果遇到左子树!=null 并且它是一个叶子节点。那么直接leftNum=node.val
代码:
public int sumOfLeftLeaves(TreeNode root) {
return getSum(root);
}
public int getSum(TreeNode root) {
if (root == null)
return 0;// 如果结点为空
if (root.left == null && root.right == null)
return 0;// 如果是叶子节点 但不一定是左
int leftSum=0;
//如果左边是一个左子节点 那么就进if条件 如果不是那么继续递归
if(root.left!=null&&root.left.left==null&&root.left.right==null){
leftSum=root.left.val;
}else{
leftSum=getSum(root.left);
}
int rightSum = getSum(root.right);// 右边的和
return leftSum + rightSum;
}
三、找树左下角的值(层序遍历/递归法)
层序遍历:
找到最后一层元素,然后返回第一个就可以。用这个很容易做出来。
List<List<Integer>> lists=new ArrayList<>();
Queue<TreeNode> queue=new ArrayDeque<>();
if(root!=null)queue.add(root);
while(!queue.isEmpty()){
List<Integer> list=new ArrayList<>();
int size=queue.size();
while(size-->0){
TreeNode node=queue.poll();
list.add(node.val);
if(node.left!=null)queue.add(node.left);
if(node.right!=null)queue.add(node.right);
}
lists.add(list);
}
return lists.get(lists.size()-1).get(0);
递归法:
1.递归函数的返回值:void 参数:TreeNode node int depth;现在的深度(当前的深度与全局变量中的max_depth做对比,如果更大就更新)
2.递归函数的终止条件:当递归到叶子结点的时候if(node.left==null&&node.right==null)
处理逻辑: if(depth>max_depth)max_depth=depth,result=node.val;(全局变量中也要定义一个result,作为返回的结果)
3.递归逻辑:
3.1.如果遇到叶子节点,那么就更新最大值。
3.2.如果结点不是叶子节点,那就继续向下遍历,先左后右。if(root.left!=null)depth++,traversal(root.left,depth),depth-- 要做回溯操作。
3.3.向右遍历 if(root.right!=null)depth++,traversal(root.right,depth),depth--
代码:
class Solution {
int max_depth=Integer.MIN_VALUE;
int result;
public int findBottomLeftValue(TreeNode root) {
traversal(root,0);
return result;
}
public void traversal(TreeNode root,int depth){
//终止条件 如果是一个叶子结点 那么就更新
if(root.left==null&&root.right==null){
if(depth>max_depth){
max_depth=depth;
result=root.val;
}
}
if(root.left!=null){
depth++;
traversal(root.left,depth);
//回溯
depth--;
}
if(root.right!=null){
depth++;
traversal(root.right,depth);
depth--;
}
}
}