二叉树初阶OJ题

翻转二叉树

链接翻转二叉树

问题描述

翻转一棵二叉树

     4
   /   \
  2     7
 / \   / \
1   3 6   9   输入
     4
   /   \
  7     2
 / \   / \
9   6 3   1   输出

分析:
从二叉树的最底层开始进行左右孩子节点交换直到根节点
代码如下:

void _invertTree(struct TreeNode* root)
{
   if(root)
   {
       struct TreeNode*tmp=root->left;
       root->left=root->right;
       root->right=tmp;
       _invertTree(root->left);
       _invertTree(root->right);
   }
}
struct TreeNode* invertTree(struct TreeNode* root){
   if(root==NULL)
       return root;
   _invertTree(root);
   return root;
}

对称二叉树

链接对称二叉树

问题描述

给定一个二叉树,检查它是否是镜像对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
    1
   / \
  2   2
 / \ / \
3  4 4  3 
但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
   1
  / \
 2   2
  \   \
   3    3

方法1分析:(递归)

  1. 当左右孩子节点均为空返回真
  2. 由于已判断left和right是否全为空,所以下一步用 ‘||’ 只要有为空的就必不相同
  3. (left->val==right->val)&&_isSymmetric(left->left,right->right)&&_isSymmetric(leftright,right->left)
    三个(第一个判断值,后两个递归)相与判断
  4. 注意: 是左孩子的左孩子和右孩子的右孩子(镜像)

方法2(迭代,进阶)初阶暂未学习
代码如下:

bool _isSymmetric(struct TreeNode* left,struct TreeNode* right)
{
   if(left==NULL&&right==NULL)
       return true;
   if(left==NULL||right==NULL)
       return false;//由于已判断left和right是否全为空,所以这里用||只要有为空的就必不相同
   return (left->val==right->val)&&
   			_isSymmetric(left->left,right->right)&&
   			_isSymmetric(left->>right,right->left);
}
bool isSymmetric(struct TreeNode* root){
   if(root==NULL)
       return true;
   return _isSymmetric(root->left,root->right);    
}

二叉树遍历(建立二叉树)

链接二叉树遍历

拓展:
只有带有空节点也就是题中的‘#’才能由先序遍历建立二叉树,
除此必须要是先序加中序后序加中序才可以建立唯一二叉树

问题描述

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

分析:

  1. 在建树函数中复用前序遍历的代码只是把打印的代码改为给root的val赋值同时数组下标++(下标传址不是传值)
  2. 为空就返回空同时下标++

代码如下:

//中序遍历打印
void InOrder(struct TreeNode* root)
{
   if(root==NULL)
       return;
   InOrder(root->left);
   printf("%c ",root->val);
   InOrder(root->right);
}
//建树
struct TreeNode* CreatTree(char *str,int *size)
{
   if(str[*size]=='#')
   {
       (*size)++;
       return NULL;
   }
   struct TreeNode*root=(struct TreeNode*)malloc(sizeof(struct TreeNode));
   root->val=str[*size];
   (*size)++;
   root->left=CreatTree(str, size);
   root->right=CreatTree(str, size);
   return root;
}

平衡二叉树

链接平衡二叉树

问题描述

给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

分析:

  1. 注意:此题不同于大多数二叉树递归,此题是从上往下判断的
  2. 辅助函数是二叉树求深度函数
  3. (abs(left-right)<=1)&&isBalanced(root->left)&&isBalanced(root->right);只要出现一个不为平衡的二叉子树就必返回false

代码如下:

int _isBalanced_Depth(struct TreeNode*root)
{
   if(root==NULL)
       return 0;
   int left=_isBalanced_Depth(root->left);
   int right=_isBalanced_Depth(root->right);
   return left>right?left+1:right+1;
}
//此方法是从上往下判断子树是否为平衡树
bool isBalanced(struct TreeNode* root){
   if(root==NULL)
       return true;
   int left=_isBalanced_Depth(root->left);
   int right=_isBalanced_Depth(root->right);
   return (abs(left-right)<=1)&&isBalanced(root->left)&&isBalanced(root->right); 
}

另一棵树的子树

链接另一棵树的子树

问题描述

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。
二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

分析:

  1. 辅助函数是判断相同的数
  2. isSubtree函数和isSametree函数中由于已判断left和right是否全为空,所以下一步用 ‘||’ 只要有为空的就必不相同
  3. 在isSubtree函数中用 ‘||’ 左边为true就不用去右边找,左边为false才到右边去找

代码如下:

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&&subRoot==NULL)
       return true;
   if(root==NULL||subRoot==NULL)
       return false;
   if(isSameTree(root, subRoot))
       return true;
   return isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
   //用 或 左边为true就>不用去右边找,左边为false才到右边去找
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值