代码随想录第十五天

110.平衡二叉树

给定一个二叉树,判断它是否是 平衡二叉树

示例 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

思路:

首先我们先创造一个用来判断一个二叉树深度的函数,运用递归的思想,当它的结点为空结点时,我们返回出的元素为0,但是如果不为0时,我们就对其使用递归,一个用来查看二叉树的左结点,一个用来查看二叉树的右结点,依次循环下去直到达到叶结点,然后返回一个最高高度。然后在判断函数中依次递归,得到左高度和右高度,来判断它们的高度是否符合平衡二叉树的要求,符合的话再判断下一个子结点,最终得到答案。

解答:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
int isnot(struct TreeNode* root)
{
    if(root == NULL)
    {
        return 0;
    }
    int left = isnot(root->left);
    int right = isnot(root->right);
    return left > right ? left+1:right+1;
}
bool isBalanced(struct TreeNode* root) {
   if(root == NULL)
   {
    return true;
   }
   int left = isnot(root->left);
   int right = isnot(root->right);
   int depth = left - right;
   if(depth > 1 || depth < -1)
   {
    return false;
   }
   return isBalanced(root->left) && isBalanced(root->right);
}

257.二叉树的所有路径

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

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

示例 1:

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

示例 2:

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

提示:

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

思路:

我们需要一个辅助函数,来帮我们进行字符串的拼接,所以我们设置一个辅助函数,首先判断根结点是否为空指针,如果是直接跳出,如果不是,在下面使用sprintf函数,它的作用是对字符串进行拼接并返回字符串元素的个数,所以我们用pathsize作为他返回的长度,接下来判断它的左右结点,如果为叶结点,那么就把之前的那些字符串复制到result里面,结束这个字符串,如果不是,就在字符串后面加上->再进行递归,最终返回答案。

解答:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
void isnot(struct TreeNode* root,char** result,int* returnSize,char* path,int pathsize)
{
    if(root == NULL)
    {
        return;
    }
    pathsize += sprintf(path+pathsize,"%d",root->val);
    if(root->left == NULL && root->right == NULL)
    {
        result[*returnSize] = malloc(sizeof(char)*(pathsize+1));
        strcpy(result[*returnSize],path);
        (*returnSize)++;
    }
    else
    {
        pathsize += sprintf(path+pathsize,"->");
        isnot(root->left,result,returnSize,path,pathsize);
        isnot(root->right,result,returnSize,path,pathsize);
    }
}
char** binaryTreePaths(struct TreeNode* root, int* returnSize) {
    char** result = malloc(sizeof(char*)*100);
    *returnSize = 0;
    char path[100];
    int pathsize = 0;
    isnot(root,result,returnSize,path,pathsize);
    return result;
}

注意:

snprintf 是 C 标准库中的一个函数,用于格式化字符串并将结果写入字符数组中。它的全称是 “string print formatted with size limit”,可以理解为有长度限制的 sprintf。它常用于安全地拼接或格式化字符串,防止缓冲区溢出。

  1. sprintf 函数的作用

    • sprintf 是 C 语言的一个标准库函数,用于格式化字符串并将结果写入指定的字符数组中。

    • 其基本格式为:

      int sprintf(char *str, const char *format, ...);
      
      • str:目标字符串的起始地址。这里就是 path + pathLen
      • format:格式化字符串。在这行代码中是 "%d",表示将整数格式化为十进制数。
      • ...:可变参数,依次填入 format 中的占位符。在这里是 root->val
  2. path + pathLen

    • path 是一个字符数组,用来存储构建中的路径字符串。
    • pathLen 表示当前路径字符串的长度,即已经写入内容的末尾位置。
    • path + pathLen 表示从路径字符串的末尾开始写入新的内容。
  3. "%d"root->val

    • "%d" 是格式化说明符,表示以十进制形式写入一个整数。
    • root->val 是要写入的整数值。
    • 例如,如果 root->val5,那么 "%d" 会被替换为 "5",并写入到 path + pathLen 的位置。
  4. 返回值

    • sprintf 的返回值是写入的字符数。
    • 如果 root->val5,写入的字符数是 1;如果 root->val10,写入的字符数是 2
  5. pathLen += 的作用

    • pathLen += 是为了更新路径字符串的长度。
    • pathLen 加上 sprintf 返回的字符数,更新为新字符串的末尾位置,方便在路径中继续追加内容。

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

思路:

这里要注意,左叶子指的是左子树并且后面没有子结点的结点,我们定义一个函数,一个是递归二叉树左结点,一个是递归二叉树的右结点,当到叶结点的上一层时,进入判断,如果有左叶子结点,那么就累计上,如果没有就看另外的结点,最后返回出来相应的答案。

解答:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
int find(struct TreeNode* root)
{
    if(root == NULL)
    {
        return 0;
    }
    int left = find(root->left);
    if(root->left != NULL && root->left->right == NULL && root->left->left == NULL)
    {
        left += root->left->val;
    }
    int right = find(root->right);
    int sum = left + right;
    return sum;
}
int sumOfLeftLeaves(struct TreeNode* root) {
    return find(root);
}

222.完全二叉树的节点个数

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

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

示例 1:

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

示例 2:

输入:root = []
输出:0

示例 3:

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

提示:

  • 树中节点的数目范围是[0, 5 * 104]
  • 0 <= Node.val <= 5 * 104
  • 题目数据保证输入的树是 完全二叉树

思路:

这是二叉树的简单操作,我们只需要把树整个遍历一遍我们就知道我们需要统计的个数了,在这里加入一个统计节点个数的变量,当整个树被遍历结束后,我们的答案也就出来了。

解答:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
void countTree(struct TreeNode* root,int* count)
{
    if(root == NULL)
    {
        return;
    }
    (*count)++;
    countTree(root->left,count);
    countTree(root->right,count);
}
int countNodes(struct TreeNode* root) {
    int count = 0;
    countTree(root,&count);
    return count;
}

反思

对于二叉树的基础运用还需要加强,但是根据今天的学习,我觉得整个人对于二叉树有了更深层次的认识,一会儿去看看层序遍历,再去理解理解。

上一篇:Lucene的使用方法与Luke工具(2)-第2章 Lucene快速入门


下一篇:Leetcode 热题100 之 二叉树3