算法训练day17leetcode110平衡二叉树257二叉树的所有路径404左叶子之和

这篇具有很好参考价值的文章主要介绍了算法训练day17leetcode110平衡二叉树257二叉树的所有路径404左叶子之和。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

今日学习的文章和视频链接

https://www.bilibili.com/video/BV1GY4y1K7z8/?vd_source=8272bd48fee17396a4a1746c256ab0ae

https://programmercarl.com/0404.%E5%B7%A6%E5%8F%B6%E5%AD%90%E4%B9%8B%E5%92%8C.html#%E6%80%9D%E8%B7%AF

题目描述

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

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

 

示例 1:


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


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

输入:root = []
输出:true
 

提示:

树中的节点数在范围 [0, 5000] 内
-104 <= Node.val <= 104

我的想法

采用后序递归遍历,比较左右子树的高度,相差小于等于1

前序,中左右,从根节点到叶子节点,会一直向下遍历下去,不会返回信息

题目分析

递归三步曲分析:

  1. 明确递归函数的参数和返回值
    参数:当前传入节点。 返回值:以当前传入节点为根节点的树的高度。

那么如何标记左右子树是否差值大于1呢?

如果当前传入节点为根节点的二叉树已经不是二叉平衡树了,还返回高度的话就没有意义了。

所以如果已经不是二叉平衡树了,可以返回-1 来标记已经不符合平衡树的规则了。

// -1 表示已经不是平衡二叉树了,否则返回值是以该节点为根节点树的高度
int getHeight(TreeNode* node)
  1. 明确终止条件
    递归的过程中依然是遇到空节点了为终止,返回0,表示当前节点为根节点的树高度为0

  2. 明确单层递归的逻辑
    如何判断以当前传入节点为根节点的二叉树是否是平衡二叉树呢?当然是其左子树高度和其右子树高度的差值。

分别求出其左右子树的高度,然后如果差值小于等于1,则返回当前二叉树的高度,否则返回-1,表示已经不是二叉平衡树了。

acm模式代码

#include <iostream>

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x):val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode* left, TreeNode* right):val(x), left(left), right(right) {}
};

class Solution {
public:
    int getNodeheight(TreeNode* node) {
        if (node == nullptr) {return 0;}
        TreeNode* left = node->left;
        int leftheight = getNodeheight(left);
        if (leftheight == -1) return -1;
        TreeNode* right = node->right;
        int rightheight = getNodeheight(right);
        if (rightheight == -1) return -1;
        int result;
        if (std::abs(leftheight - rightheight) > 1) result = -1;
        else {result = 1 + std::max(leftheight, rightheight);}
        return result;
    }
    bool isBalanced(TreeNode* root) {
        int result = getNodeheight(root);
        if (result != -1) return true;
        else {return false;}
    }
};



int main() {
    // 创建树的节点
    TreeNode *root = new TreeNode(1);
    root->left = new TreeNode(2);
    root->right = new TreeNode(3);
    root->left->left = new TreeNode(4);
    root->left->right = new TreeNode(5);
    root->right->right = new TreeNode(6);

    // 可以继续添加更多的节点来构造树
    // ...

    // 创建Solution实例并检查树是否平衡
    Solution solution;
    bool isTreeBalanced = solution.isBalanced(root);

    if (isTreeBalanced) {
        std::cout << "The tree is balanced." << std::endl;
    } else {
        std::cout << "The tree is not balanced." << std::endl;
    }

    // 释放树的节点内存(简单示例,适用于小树)
    delete root->left->left;
    delete root->left->right;
    delete root->right->right;
    delete root->left;
    delete root->right;
    delete root;

    return 0;
}

257 二叉树的所有路径

题目描述

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

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

 
示例 1:


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

输入:root = [1]
输出:["1"]
 

提示:

树中节点的数目在范围 [1, 100] 内
-100 <= Node.val <= 100

我的想法

从上到下,用前序递归遍历

题目分析

在这道题目中将第一次涉及到回溯,因为我们要把路径记录下来,需要回溯来回退一个路径再进入另一个路径。

我们先使用递归的方式,来做前序遍历。要知道递归和回溯就是一家的,本题也需要回溯。

#递归
递归函数参数以及返回值
要传入根节点,记录每一条路径的path,和存放结果集的result,这里递归不需要返回值,代码如下:

void traversal(TreeNode* cur, vector& path, vector& result)
确定递归终止条件
在写递归的时候都习惯了这么写:

if (cur == NULL) {
    终止处理逻辑
}

但是本题的终止条件这样写会很麻烦,因为本题要找到叶子节点,就开始结束的处理逻辑了(把路径放进result里)。

那么什么时候算是找到了叶子节点? 是当 cur不为空,其左右孩子都为空的时候,就找到叶子节点。

所以本题的终止条件是:

if (cur->left == NULL && cur->right == NULL) {
    终止处理逻辑
}

回溯要和递归永远在一起,世界上最遥远的距离是你在花括号里,而我在花括号外!

那么代码应该这么写:

if (cur->left) {
    traversal(cur->left, path, result);
    path.pop_back(); // 回溯
}
if (cur->right) {
    traversal(cur->right, path, result);
    path.pop_back(); // 回溯
}

完整代码

class Solution {
private:

    void traversal(TreeNode* cur, vector<int>& path, vector<string>& result) {
        path.push_back(cur->val); // 中,中为什么写在这里,因为最后一个节点也要加入到path中 
        // 这才到了叶子节点
        if (cur->left == NULL && cur->right == NULL) {
            string sPath;
            for (int i = 0; i < path.size() - 1; i++) {
                sPath += to_string(path[i]);
                sPath += "->";
            }
            sPath += to_string(path[path.size() - 1]);
            result.push_back(sPath);
            return;
        }
        if (cur->left) { // 左 
            traversal(cur->left, path, result);
            path.pop_back(); // 回溯
        }
        if (cur->right) { // 右
            traversal(cur->right, path, result);
            path.pop_back(); // 回溯
        }
    }

public:
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> result;
        vector<int> path;
        if (root == NULL) return result;
        traversal(root, path, result);
        return result;
    }
};

404 左叶子之和

题目分析

定二叉树的根节点 root ,返回所有左叶子之和。

示例 1:

输入: root = [3,9,20,null,null,15,7]
输出: 24
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
示例 2:

输入: root = [1]
输出: 0

提示:

节点数在 [1, 1000] 范围内
-1000 <= Node.val <= 1000

题目分析

首先要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。

因为题目中其实没有说清楚左叶子究竟是什么节点,那么我来给出左叶子的明确定义:节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点

那么判断当前节点是不是左叶子是无法判断的,必须要通过节点的父节点来判断其左孩子是不是左叶子。

如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子,判断代码如下:

if (node->left != NULL && node->left->left == NULL && node->left->right == NULL) {
    左叶子节点处理逻辑
}

递归法

递归的遍历顺序为后序遍历(左右中),是因为要通过递归函数的返回值来累加求取左叶子数值之和。

递归三部曲:

  1. 确定递归函数的参数和返回值
    判断一个树的左叶子节点之和,那么一定要传入树的根节点,递归函数的返回值为数值之和,所以为int

使用题目中给出的函数就可以了。

  1. 确定终止条件
    如果遍历到空节点,那么左叶子值一定是0
if (root == NULL) return 0;
if (root->left == NULL && root->right== NULL) return 0; //其实这个也可以不写,如果不写不影响结果,但就会让递归多进行了一层。
  1. 确定单层递归的逻辑
    当遇到左叶子节点的时候,记录数值,然后通过递归求取左子树左叶子之和,和 右子树左叶子之和,相加便是整个树的左叶子之和。

代码如下:文章来源地址https://www.toymoban.com/news/detail-803812.html

int leftValue = sumOfLeftLeaves(root->left);    // 左
if (root->left && !root->left->left && !root->left->right) {
    leftValue = root->left->val;
}
int rightValue = sumOfLeftLeaves(root->right);  // 右

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

整体代码

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 && !root->left->left && !root->left->right) { // 左子树就是一个左叶子的情况
            leftValue = root->left->val;
        }
        int rightValue = sumOfLeftLeaves(root->right);  // 右

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

到了这里,关于算法训练day17leetcode110平衡二叉树257二叉树的所有路径404左叶子之和的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【LeetCode】110. 平衡二叉树

    思路 对二叉树做先序遍历, 从底至顶返回子树最大高度 ,若判定 某子树不是平衡树则“剪枝”直接向上返回 。 递归返回值 : 当节点 root 左、右子树的高度差 1:返回 -1,代表此子树不是平衡树; 否则返回以节点 root 为根节点的 子树的最大高度 ,即节点 root 的左、右子树

    2024年02月08日
    浏览(43)
  • LeetCode | 110. 平衡二叉树

    OJ链接 首先计算出二叉树的高度 然后计算当前节点的左右子树的高度,然后判断当前节点的左右子树高度差是否超过 1,最后递归地检查左右子树是否也是平衡的。

    2024年02月04日
    浏览(50)
  • 【深度优先】【广度优先】Leetcode 104 二叉树的最大深度 Leetcode 111 二叉树的最小深度 Leetcode 110 平衡二叉树

    二叉树节点的深度: 指从根节点到该节点的最长简单路径边的条数或者节点数 (取决于深度从0开始还是从1开始) 二叉树节点的高度: 指从该节点到叶子节点的最长简单路径边的条数后者节点数 (取决于高度从0开始还是从1开始) 【前序求的是深度,后序求的是高度】 -

    2024年02月19日
    浏览(53)
  • 代码随想录day21(2)二叉树:二叉树的所有路径(leetcode257)

    题目要求:按任意顺序返回所有从根节点到叶节点的路径 思路:我们先递归地进行前序遍历,同时要注意回溯的过程,注意一些库的用法即可。 leetcode实战: 代码实现:

    2024年03月18日
    浏览(49)
  • 算法训练day15Leetcode102二叉树层序遍历226翻转二叉树101对称二叉树

    https://www.bilibili.com/video/BV1ue4y1Y7Mf/?vd_source=8272bd48fee17396a4a1746c256ab0ae 层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。 需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先

    2024年01月18日
    浏览(56)
  • 算法训练day16Leetcode104二叉树最大深度111二叉树最小深度222完全二叉树的节点个数

    https://www.bilibili.com/video/BV1Gd4y1V75u/?vd_source=8272bd48fee17396a4a1746c256ab0ae 用递归,但是什么顺序没想清楚 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始) 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边

    2024年01月16日
    浏览(44)
  • 算法训练day20Leetcode654最大二叉树617合并二叉树700二叉树中的1搜索98验证二叉搜索树

    https://leetcode.cn/problems/maximum-binary-tree/description/ 中序遍历递归,找到最大值然后作为根节点 凡是构造二叉树的题目都用前序遍历 (中左右) 为先构造中间节点,然后递归构造左子树和右子树。 确定递归函数的参数和返回值 参数传入的是存放元素的数组,返回该数组构造的二

    2024年01月21日
    浏览(42)
  • 算法训练day13Leetcode144 145 94 二叉树的前(中)(后)序遍历

    https://www.bilibili.com/video/BV1Hy4y1t7ij/?vd_source=8272bd48fee17396a4a1746c256ab0ae 二叉树的种类 在我们解题过程中二叉树有两种主要的形式:满二叉树和完全二叉树。 满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。 什么

    2024年01月15日
    浏览(55)
  • 110. 平衡二叉树【75】

    难度等级:容易 上一篇算法: 102. 二叉树的层序遍历【206】 力扣此题地址: 110. 平衡二叉树 - 力扣(Leetcode) 给定一个二叉树,判断它是否是高度平衡的二叉树。 本题中,一棵高度平衡二叉树定义为: 一个二叉树 每个节点  的左右两个子树的高度差的绝对值不超过 1 。  

    2023年04月22日
    浏览(39)
  • 力扣 110. 平衡二叉树

    题目来源:https://leetcode.cn/problems/balanced-binary-tree/description/     C++题解1:递归法,后续遍历,从叶子节点开始,判断左右子树的深度差是否大于1。 代码随想录:思想是一致的,当为不平衡树时可以节省右子树的遍历。 C++题解2:迭代法,较为繁琐。由根节点往叶子节点需计

    2024年02月11日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包