代码随想录算法训练营第15天 | 110.平衡二叉树、257. 二叉树的所有路径、404.左叶子之和、222.完全二叉树的节点个数

110.平衡二叉树 (优先掌握递归)

题目链接/文章讲解/视频讲解
再一次涉及到,什么是高度,什么是深度,可以巩固一下。

思路

  • 任何节点的左右子树高度差小于等于1则是平衡二叉树
  • 高度和深度:高度:到叶子节点的距离;深度:到根节点的距离。这道题求高度,就是后序遍历。

伪代码

//定义递归函数,参数和返回值
private int getHeight(TreeNode root){
    //终止条件  空节点高度为0
    if(node == null) return 0;  
    //发现任何一个节点不符合平衡二叉树的定义,直接返回-1
    //采用后序遍历  左右中
    int leftHeight = getHeight(root.left);  //左子树高度
    if(leftHeight == -1)  return -1;  //左子树高度==-1不符合平衡二叉树
    int rightHeight = getHeight(root.right);  //右子树高度
    if(rightHeight == -1) return -1;
    int result;
    //  一定要把中写在左右子树的后面,才能获取左右的情况返回给父节点
    if(Math.abs(leftHeight - rightHeight)  > 1){  //相减绝对值大于1  
        result = -1;
    }else{
      //  左右子树高度取最大值再加一
        result = Math.max(leftHeight, rightHeight) + 1;
    }
    return result;
}
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isBalanced(TreeNode root) {
        return getHeight(root) != -1;  //为什么这里要这么写
    }
    private int getHeight(TreeNode root){
        if(root == null) return 0;
        int leftHeight = getHeight(root.left);
        if(leftHeight == -1) return -1;
        int rightHeight = getHeight(root.right); 
        if(rightHeight == -1) return -1;
        return Math.abs(leftHeight - rightHeight) > 1 ? -1 : (Math.max(leftHeight, rightHeight) + 1);
    }
}

257. 二叉树的所有路径 (优先掌握递归)

题目链接/文章讲解/视频讲解

思路

  • 返回从根节点到叶子节点的所有路径
  • 使用前序遍历:这样才能让父节点指向孩子节点,才能把路径输出出来
  • 只要有递归就一定有回溯
    • 为什么会有回收的过程:一个容器来收集路径,怎么把一条路径收集完后,把子节点弹出去,重新回到根节点记录新路径呢?所以有回溯。

伪代码

//1. 定义函数,定义参数和返回值
// root 根节点; paths 记录单条路径的数组;res  记录最后结果,也是返回值
 private void traversal(TreeNode node, List<Integer> paths, List<String> res) {
//3. 前序遍历,中节点,因为遍历到叶子节点就结束了,所以要把叶子节点放进入才中止
paths.add(node.val);
//2. 确定终止条件:遍历到叶子节点
if(node.left == null && node.right == null){
    // 要把paths转化成String然后元素之间加上"->",代码略
    StringBuilder sb = new StringBuilder();// StringBuilder用来拼接字符串
    ……
    res.add(sb.toString())
    return;
  }
//向左递归
if(node != null){
    traversal(root.left, paths, res);
    paths.remove(paths.size() - 1);// 回溯,可以隐藏在参数中
}
//向右递归
if(node != null){
    traversal(root.right, paths, res);
    paths.remove(paths.size() - 1);// 回溯
}

    
}
}

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> res = new ArrayList<>();// 存最终的结果
        if (root == null) {
            return res;
        }
        List<Integer> paths = new ArrayList<>();// 作为结果中的路径
        traversal(root, paths, res);
        return res;
        
    }

    private void traversal(TreeNode root, List<Integer> paths, List<String> res){
        paths.add(root.val);
        if(root.left == null && root.right == null){
            StringBuilder s = new StringBuilder();
            for(int i = 0; i < paths.size()-1; i++){
                s.append(paths.get(i)).append("->");
            }
            s.append(paths.get(paths.size() - 1));
            res.add(s.toString());
            return;
        }
        if(root.left != null){
            traversal(root.left, paths, res);
            paths.remove(paths.size()-1);
        }
        if(root.right != null){
            traversal(root.right, paths, res);
            paths.remove(paths.size()-1);
        }
    }
}

404.左叶子之和 (优先掌握递归)

题目链接/文章讲解/视频讲解
其实本题有点文字游戏,搞清楚什么是左叶子,剩下的就是二叉树的基本操作。

思路

  • 左叶子节点的定义:一定是叶子节点(子节点为空);一定是父节点的左孩子。
  • 和之前二叉树题目的区别:无法判断叶子节点是不是父节点的左孩子,所以判断条件是:一个节点的左孩子不为空,同时左孩子的左右孩子都为空。
  • 使用后序遍历,因为要一层一层向上返回

伪代码

public int sumOfLeftLeaves(TreeNode root) {
    //终止条件
    if(root == null) return 0;
    if(root.left == null && root.right == null) return 0; // 不写也行,只是递归多了一层
    //单层递归的逻辑
    
    int leftNum = sumOfLeftLeaves(root.left);
    //左孩子不为空,同时左孩子为叶子节点
    if(root.left != null && root.left.left != null && root.right.right != null){
        leftNum = root.left.val;
    }
    int rightNum = sumOfLeftLeaves(root.right);
    int sum = leftNum + rightNum
    return sum; 
}
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        if (root == null) return 0;
        if (root.left == null && root.right == null) return 0;

        int leftValue = sumOfLeftLeaves(root.left);    // 左
        if (root.left != null && root.left.left == null && root.left.right == null) { // 左子树就是一个左叶子的情况
            leftValue = root.left.val;
        }
        int rightValue = sumOfLeftLeaves(root.right);  // 右

        int sum = leftValue + rightValue;               // 中
        return sum;
    }
}

222.完全二叉树的节点个数(优先掌握递归)

题目链接/文章讲解/视频讲解
需要了解,普通二叉树 怎么求,完全二叉树又怎么求

思路

  • 如果是普通的二叉树,就是遍历节点

后序遍历

class Solution {
    // 通用递归解法
    public int countNodes(TreeNode root) {
        if(root == null) {
            return 0;
        }
        return countNodes(root.left) + countNodes(root.right) + 1;
    }
}
  • 利用完全二叉树的特性的写法
  • 完全二叉树的定义:除了底层节点每一层都是满的,底层节点都集中在该层最左边
  • 只要知道深度,节点数量就是2的深度次方 -1
  • 所以就是左子树的数量+右子树的数量+1
  • 如果是满二叉树,往左右两边遍历的深度相等;如果子树不相等则不是满二叉树,那么就继续向下递归,一定可以遇到符合满足条件的节点
public int countNodes(TreeNode root) {
//终止条件
        if (root == null) return 0;
        //遇到子树为满二叉树,也要返回结果并终止
        TreeNode left = root.left;
        TreeNode right = root.right;
        int leftDepth = 0, rightDepth = 0; // 这里初始为0是有目的的,为了下面求指数方便
        while (left != null) {  // 求左子树深度
            left = left.left;
            leftDepth++;
        }
        while (right != null) { // 求右子树深度
            right = right.right;
            rightDepth++;
        }
        if (leftDepth == rightDepth) {
            return (2 << leftDepth) - 1; // 注意(2<<1) 相当于2^2,所以leftDepth初始为0
        }
        return countNodes(root.left) + countNodes(root.right) + 1;
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容