二叉树相关的算法题

二叉树相关的算法题

单值二叉树

如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。

只有给定的树是单值二叉树时,才返回 true;否则返回 false

示例 1:

输入:[1,1,1,1,1,null,1]
输出:true

示例 2:

输入:[2,2,2,5,2]
输出:false

提示:

  1. 给定树的节点数范围是 [1, 100]
  2. 每个节点的值都是整数,范围为 [0, 99]

思路如下:

代码如下:

C 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
 typedef struct TreeNode TreeNode;
bool isUnivalTree(struct TreeNode* root) {
    //根节点为空
    if(root==NULL)
    {
        return true;
    }
    //根节点不为空
    if(root->left&&root->left->val!=root->val)
    {
        return false;
    }
    if(root->right&&root->right->val!=root->val)
    {
        return false;
    }
    return isUnivalTree(root->left)&&isUnivalTree(root->right);
}

相同的树

给你两棵二叉树的根节点 pq ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:

输入:p = [1,2,3], q = [1,2,3]
输出:true

示例 2:

输入:p = [1,2], q = [1,null,2]
输出:false

示例 3:

代码如下:

C 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
   //该树为空
    if(p==NULL&&q==NULL)
    {
        return true;
    }
    //其中一个为空
    if(p==NULL||q==NULL)
    {
        return false;
    }
    //值不同
    if(p->val!=q->val)
    {
        return false;
    }
    return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right);
}

对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。

示例 1:

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

示例 2:

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

提示:

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

++这道题是基于上一题相同的树来完成的。++

代码如下:

C 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
 bool isSameTree(struct TreeNode*p,struct TreeNode*q)
 {
    if(p==NULL&&q==NULL)
    {
        return true;
    }
    if(p==NULL||q==NULL)
    {
        return false;
    }
    if(p->val!=q->val)
    {
        return false;
    }
    return isSameTree(p->left,q->right)&&isSameTree(p->right,q->left);//不同点在于这里两个树的结构进行比较,不是说树的内部进行比较
 }
bool isSymmetric(struct TreeNode* root) {
    return isSameTree(root->left,root->right);
}

另一个树的子树

给你两棵二叉树 rootsubRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

示例 1:

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

示例 2:

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

提示:

  • root 树上的节点数量范围是 [1, 2000]
  • subRoot 树上的节点数量范围是 [1, 1000]
  • -104 <= root.val <= 104
  • -104 <= subRoot.val <= 104

代码如下:

C 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

bool isSameTree(struct TreeNode*p,struct TreeNode*q)
{
    if(p==NULL&&q==NULL)
    {
        return true;
    }
    if(p==NULL||q==NULL)
    {
        return false;
    }
    if(p->val!=q->val)
    {
        return false;
    }
    return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
    if(root==NULL)
    {
        return false;
    }
    if(isSameTree(root,subRoot))
    {
        return true;
    }
    return isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
}

这几道题我们可以发现重要的规律,都要用到相同的二叉树里面的代码,这里有所不同的地方在于让根节点的左右子树分别和subRoot进行比较。

二叉树的前序遍历

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

示例 1:

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

示例 2:

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

示例 3:

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

示例 4:

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

示例 5:

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

提示:

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

代码如下:

C 复制代码
/**
 * 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().
 */
 typedef struct TreeNode TreeNode;
 int TreeSize(TreeNode*root)
 {
    if(root==NULL)
    {
        return 0;
    }
    return 1+TreeSize(root->left)+TreeSize(root->right);
 }
//前序遍历:根左右
 void _preorderTraversal(TreeNode*root,int*arr,int*pi)
 {
    if(root==NULL)
    {
        return;
    }
     //为什么这里不是传值,而是要传地址呢,因为传值是放到另一块空间,并没有改变本身,也就意味着,从始至终都是从0开始
     //形参要想改变实参就要传址调用
    arr[(*pi)++]=root->val;
    _preorderTraversal(root->left,arr,pi);
    _preorderTraversal(root->right,arr,pi);
 }
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    //求节点个数
    *returnSize=TreeSize(root);
    //计算数组大小
    int*returnArr=(int*)malloc(sizeof(int)*(*returnSize));
    int i=0;
    _preorderTraversal(root,returnArr,&i);
    return returnArr;
}

二叉树的中序遍历

给定一个二叉树的根节点 root ,返回 它的 中序 遍历

示例 1:

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

示例 2:

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

示例 3:

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

提示:

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

代码如下:

C 复制代码
/**
 * 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().
 */
 typedef struct TreeNode TreeNode;
 int TreeSize(TreeNode*root)
 {
    if(root==NULL)
 {
    return 0;
 }
 return 1+TreeSize(root->left)+TreeSize(root->right);
 }

 void _inorderTraversal(struct TreeNode*root,int*arr,int*pi)
 {
    if(root==NULL)
    {
        return;
    }
   _inorderTraversal(root->left,arr,pi);
    arr[(*pi)++]=root->val;
    _inorderTraversal(root->right,arr,pi);
 }
int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    *returnSize=TreeSize(root);
    int* returnArr=(int*)malloc(sizeof(int)*(*returnSize));
    int i=0;
    _inorderTraversal(root,returnArr,&i);
    return returnArr;
}

二叉树的后序遍历

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 树中节点的数目在范围 [0, 100]
  • -100 <= Node.val <= 100
C 复制代码
/**
 * 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().
 */
 typedef struct TreeNode TreeNode;
 int TreeSize(TreeNode*root)
 {
    if(root==NULL)
    {
        return 0;
    }
    return 1+TreeSize(root->left)+TreeSize(root->right);
 }
void _postorderTraversal(struct TreeNode*root,int*arr,int*pi)
{
    if(root==NULL)
    {
        return;
    }
    _postorderTraversal(root->left,arr,pi);
    _postorderTraversal(root->right,arr,pi);
    arr[(*pi)++]=root->val;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize) {
    *returnSize=TreeSize(root);
    int*returnArr=(int*)malloc(sizeof(int)*(*returnSize));
    int i=0;
    _postorderTraversal(root,returnArr,&i);
    return returnArr;
}

这三道题我们可以感受到只要掌握了怎样遍历二叉树就会变得简单许多

二叉树遍历

描述

编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中"#"表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。

输入描述:

输入包括1行字符串,长度不超过100。

输出描述:

可能有多组测试数据,对于每组数据, 输出将输入字符串建立二叉树后中序遍历的序列,每个字符后面都有一个空格。 每个输出结果占一行。

示例1

abc##de#g##f###
c b e g d f a 

思路如下:

代码如下:

C 复制代码
include <stdio.h>
#include <stdlib.h>
typedef struct BinaryTreeNode
{
    char data;
     struct BinaryTreeNode*left;
     struct BinaryTreeNode*right;
}BTNode;
BTNode* BuyNode(char x)
{
    BTNode*newnode=(BTNode*)malloc(sizeof(BTNode));
    newnode->data=x;
    newnode->left=newnode->right=NULL;
    return newnode;
}
BTNode*CreateNode(char*arr,int*pi)
{
    if(arr[*pi]=='#')
    {
        (*pi)++;
        return NULL;
    }
    BTNode*root=BuyNode(arr[(*pi)++]);
    root->left=CreateNode(arr, pi);
    root->right=CreateNode(arr, pi);
    return root;
}
 void Inorder(BTNode*root)
{
    if(root==NULL)
    {
        return;
    }
    Inorder(root->left);
    printf("%c ",root->data);
    Inorder(root->right);
}
int main() {
    char arr[100];
    scanf(" %s ",arr);
    int i=0;
    BTNode*root=CreateNode(arr,&i);
    Inorder(root);
    return 0;
}
相关推荐
EricWang135832 分钟前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
我是谁??34 分钟前
C/C++使用AddressSanitizer检测内存错误
c语言·c++
小码农<^_^>36 分钟前
优选算法精品课--滑动窗口算法(一)
算法
羊小猪~~38 分钟前
神经网络基础--什么是正向传播??什么是方向传播??
人工智能·pytorch·python·深度学习·神经网络·算法·机器学习
软工菜鸡1 小时前
预训练语言模型BERT——PaddleNLP中的预训练模型
大数据·人工智能·深度学习·算法·语言模型·自然语言处理·bert
南宫生1 小时前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
希言JY1 小时前
C字符串 | 字符串处理函数 | 使用 | 原理 | 实现
c语言·开发语言
午言若1 小时前
C语言比较两个字符串是否相同
c语言
AI视觉网奇2 小时前
sklearn 安装使用笔记
人工智能·算法·sklearn
JingHongB2 小时前
代码随想录算法训练营Day55 | 图论理论基础、深度优先搜索理论基础、卡玛网 98.所有可达路径、797. 所有可能的路径、广度优先搜索理论基础
算法·深度优先·图论