算法Day13|110-平衡二叉树;257-二叉树的所有路径;404-左叶子之和;222-完全二叉树的节点个数

67 阅读3分钟

1、题目1:110-平衡二叉树

题目:leetcode.cn/problems/ba…

类型:简单

平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

输入: root = [3,9,20,null,null,15,7] 输出: true

输入: root = [1,2,2,3,3,null,null,4,4] 输出: false

思路:递归法

public class Number110_1 {

    public boolean isBalanced(TreeNode root) {
        if(root == null){
            return true;
        }
        return compareTree(root)==-1?true:false;
    }

    // 后序遍历
    private int compareTree(TreeNode node) {
        if(node == null){
            return 0;
        }
        int leftLen = compareTree(node.left); // 左子树的高度
    if(leftLen == -1){
            return -1;
        }
        int rightLen = compareTree(node.right);
        if(rightLen ==-1){
            return -1;
        }
        if(Math.abs(leftLen-rightLen)>1){
            return -1;
        }
        return 1+Math.max(leftLen,rightLen);
    }
}

2、题目2:257-二叉树的所有路径

题目:leetcode.cn/problems/bi…

类型:简单

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

叶子节点 是指没有子节点的节点。

输入: root = [1,2,3,null,5] 输出: ["1->2->5","1->3"]

思路:我们使用前序遍历,只有前序遍历,才能让父节点指向孩子节点。

这道题有回溯的。因为我们要把所有路径都记录下来,需要回溯回退一个路径再进入另一个路径。

使用递归:

1、递归函数参数以及返回值。

要传入根结点,记录每一条路径的 path,和存放结果集的result,这里递归不需要返回值;

void traversal(TreeNode root, List<Integer> paths, List<String> res)

2、确定递归终止条件

我们的逻辑是处理找到叶子节点,当cur 不为空,且左右孩子都为空的时候,就找到叶子节点/

所以本题的终止条件是:

if(cur.left == null && cur.right == null){
   // 终止处理逻辑
}

3、确定单层逻辑

因为是前序遍历,需要先处理中间节点,中间节点就是我们要记录路径上的节点,先放进 path 中。

path.push(cur.val)

在递归的时候,因为没有判断 cur 是否为空

回溯和递归是一一对应的,有一个递归,就要有一个回溯。

public static List<String> binaryTreePaths(TreeNode root) {
    ArrayList<String> list = new ArrayList<>();
    if(root == null){
        return list;
    }
    ArrayList<Integer> paths = new ArrayList<>(); // 作为结果中的路径
traveList(root,paths,list);
    return list;
}

private static void traveList(TreeNode root, ArrayList<Integer> paths, ArrayList<String> list) {
    // 前序遍历
paths.add(root.val);
    // 遇到叶子节点
if(root.left == null && root.right ==null){
        // 输出
StringBuilder builder = new StringBuilder();
        for (Integer path : paths) {
            builder.append(path).append("->");
        }
        // 删除最后的箭头
builder.delete(builder.length()-2,builder.length());
        list.add(builder.toString()); //收集到最后的路径
return;
    }
    // 递归和回溯同时进行
if(root.left !=null){
        traveList(root.left,paths,list);
        paths.remove(paths.size()-1); //回溯
}
    if(root.right !=null){
        traveList(root.right,paths,list);
        paths.remove(paths.size()-1);
    }
}

3、题目3:404-左叶子之和

题目:leetcode.cn/problems/su…

计算给定二叉树的所有左叶子之和。

示例:

思路:在递归的本层处理逻辑中,判断节点是否为左叶子是无法判断的,必须要通过节点的父节点来判断其左孩子是不是左叶子。

如果该节点的左节点不为空,且该节点的左节点的左节点为空,且该节点的左节点的右节点为空,则找到一个左叶子。

递归三部曲:

1、入参,出参

int getSum(TreeNode root)

2、递归结束条件

if(node == null){
   return 0; // 代表没找到
}
if(node.left == null && node.right ==null){
  return 0;
}

3、本轮递归的处理逻辑

int leftSum = getSum(node.left);
if(node.left !=null && node.left.left==null && node.left.right == null){
   leftSum =node.left.val;// 找到左节点,返回左节点的值
}
int rightSum = getSum(node.right);
return leftSum+rightSum;
public static int sumOfLeftLeaves(TreeNode root) {
    if(root == null){
        return 0; // 代表没找到
}
    int leftSum = sumOfLeftLeaves(root.left); // 左递归

if(root.left !=null && root.left.left==null && root.left.right == null){
        leftSum = root.left.val; // 找到左节点,返回左节点的值
}
    int rightSum = sumOfLeftLeaves(root.right);

    return leftSum+rightSum;
}

4、题目4:222-完全二叉树的节点个数

题目:leetcode.cn/problems/co…

类型:简单

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2(h) 个节点。

输入: root = [1,2,3,4,5,6] 输出: 6

当成普通二叉树算即可

class Solution {
    // 通用递归解法
public int countNodes(TreeNode root) {
        if(root == null) {
            return 0;
        }
        return countNodes(root.left) + countNodes(root.right) + 1;
    }
}