剑指Offer - 面试题28:对称的二叉树

简介: 剑指Offer - 面试题28:对称的二叉树

题目

请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。例如,在下图中,只有第一颗二叉树是对称的。而另外俩颗不是。


分析

对称遍历

对称的二叉树本质就是左右节点相同就好,所以我们可以用俩种对称的遍历方法将指向节点的指针存入容器中(如果放的是节点值的话,就如上图第三个二叉树,会造成混乱),然后一一对比,若有不同时就表示不是对称二叉树。

选取:根左右根右左 做对比

C++

#include <iostream>
#include <vector>
using namespace std;
typedef int TElemType;  //树结点的数据类型,目前暂定为整型
struct BinaryTreeNode
{
  TElemType m_nValue;
  BinaryTreeNode* m_pLeft;//左孩子节点
  BinaryTreeNode* m_pRight;//右孩子节点
};
void CreatTree(BinaryTreeNode** T)
{
  TElemType elem;
  cin >> elem;
  if (elem != 999)
  {
    *T = new BinaryTreeNode();
    if (NULL == T)
    {
      return;
    }
    (*T)->m_nValue = elem;
    CreatTree(&((*T)->m_pLeft));
    CreatTree(&((*T)->m_pRight));
  }
  else
  {
    *T = nullptr;
  }
}
void RootRightLeft(BinaryTreeNode* root, vector<BinaryTreeNode*>& v)//前序遍历 根左右
{
  if (NULL == root)
  {
    return;
  }
  v.push_back(root);
  RootRightLeft(root->m_pLeft, v);
  RootRightLeft(root->m_pRight, v);
}
void RootLeftRight(BinaryTreeNode* root, vector<BinaryTreeNode*>& v)// 根右左
{
  if (NULL == root)
  {
    return;
  }
  v.push_back(root);
  RootLeftRight(root->m_pRight, v);
  RootLeftRight(root->m_pLeft, v);
}
bool Comparison(vector<BinaryTreeNode*>& v1, vector<BinaryTreeNode*>& v2)//对比俩容器
{
  //参数出现异常
  if (v1.size() < 0 || v2.size() < 0 || v1.size() != v2.size())
  {
    return false;
  }
  int size = v1.size();
  int i = 0;
  for (i = 0; i < size; i++)
  {
    if (v1.at(i) != v2.at(i))
    {
      return false;
    }
  }
  cout << "size = " << size << endl;
  return true;
}
bool isSymmetrical(BinaryTreeNode* pRoot)
{
  vector<BinaryTreeNode*> v1;//用于存放 根左右 的遍历结果
  vector<BinaryTreeNode*> v2;//用于存放 根右左 的遍历结果
  RootRightLeft(pRoot, v1);
  RootLeftRight(pRoot, v2);
  return Comparison(v1, v2);
}
int main()
{
  BinaryTreeNode* root = nullptr;
  cout << "请按照先序遍历规则输入节点值(输入999表示当前为空):" << endl;
  CreatTree(&root);
  bool ret = isSymmetrical(root);
  if (ret == true)
  {
    cout << "该二叉树是对称二叉树" << endl;
  }
  else
  {
    cout << "该二叉树不是对称二叉树" << endl;
  }
  return 0;
}


测试数据为题目的三个二叉树

递归法

我们还可以拿递归来实现,省掉了空间存储。

递归信息

  • 当传入俩节点均为nullptr就返回true
  • 当传入俩节点有一个nullptr就返回false;因为这是俩边已经不同了
  • 当传入俩节点的值相同时就继续递归,反之直接false;不能有一次false


C++

#include <iostream>
#include <vector>
using namespace std;
typedef int TElemType;  //树结点的数据类型,目前暂定为整型
struct BinaryTreeNode
{
  TElemType m_nValue;
  BinaryTreeNode* m_pLeft;//左孩子节点
  BinaryTreeNode* m_pRight;//右孩子节点
};
void CreatTree(BinaryTreeNode** T)
{
  TElemType elem;
  cin >> elem;
  if (elem != 999)
  {
    *T = new BinaryTreeNode();
    if (NULL == T)
    {
      return;
    }
    (*T)->m_nValue = elem;
    CreatTree(&((*T)->m_pLeft));
    CreatTree(&((*T)->m_pRight));
  }
  else
  {
    *T = nullptr;
  }
}
bool Recursion(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)//递归
{
  if (nullptr == pRoot1 && nullptr == pRoot2)//同时达底
  {
    return true;
  }
  if (nullptr == pRoot1 || nullptr == pRoot2)//有一边提前完
  {
    return false;
  }
  if (pRoot1->m_nValue != pRoot2->m_nValue)
  {
    return false;
  }
  //对比 proot1的左儿子和proot2的右儿子
  //对比 proot2的左儿子和proot1的右儿子   都必须相等。
  return Recursion(pRoot1->m_pLeft, pRoot2->m_pRight) && 
    Recursion(pRoot1->m_pRight, pRoot2->m_pLeft);
}
bool isSymmetrical(BinaryTreeNode* pRoot)//二叉树是否对称
{
  return Recursion(pRoot, pRoot);
}
int main()
{
  BinaryTreeNode* root = nullptr;
  cout << "请按照先序遍历规则输入节点值(输入999表示当前为空):" << endl;
  CreatTree(&root);
  bool ret = isSymmetrical(root);
  if (ret == true)
  {
    cout << "该二叉树是对称二叉树" << endl;
  }
  else
  {
    cout << "该二叉树不是对称二叉树" << endl;
  }
  return 0;
}

测试数据

本章完!


目录
相关文章
|
3月前
|
算法
二叉树面试题
本文介绍了二叉树相关的几个经典算法问题。首先讲解了如何判断两棵树是否完全相同(LeetCode 100),并给出了代码示例。接着讨论了如何判断一棵树是否是另一棵树的子树(LeetCode 572),详细分析了子树的定义及判断方法。然后介绍了翻转二叉树(LeetCode 226)的实现方法,即在遍历时交换每个节点的左右子树。随后探讨了如何判断一棵树是否是对称的(LeetCode 101),通过对左右子树的递归比较来实现。最后分析了平衡二叉树的概念(LeetCode 110)及判断方法,并给出了优化后的代码示例。此外,还简要介绍了二叉树遍历及二叉树最近公共祖先(LeetCode 236)的问题
31 6
二叉树面试题
|
1月前
|
算法 Java
JAVA 二叉树面试题
JAVA 二叉树面试题
19 0
|
4月前
|
安全 编译器 C++
【剑指offer】2.2编程语言(p22-p25)——面试题1:string赋值运算函数
【剑指offer】2.2编程语言(p22-p25)——面试题1:string赋值运算函数
|
7月前
【一刷《剑指Offer》】面试题 23:从上往下打印二叉树
【一刷《剑指Offer》】面试题 23:从上往下打印二叉树
|
7月前
【一刷《剑指Offer》】面试题 22:栈的压入、弹出系列
【一刷《剑指Offer》】面试题 22:栈的压入、弹出系列
|
7月前
|
算法
【一刷《剑指Offer》】面试题 21:包含 main 函数的栈
【一刷《剑指Offer》】面试题 21:包含 main 函数的栈
|
7月前
【一刷《剑指Offer》】面试题 20:顺时针打印矩阵
【一刷《剑指Offer》】面试题 20:顺时针打印矩阵
|
7月前
【一刷《剑指Offer》】面试题 19:二叉树的镜像
【一刷《剑指Offer》】面试题 19:二叉树的镜像
|
7月前
【一刷《剑指Offer》】面试题 18:树的子结构
【一刷《剑指Offer》】面试题 18:树的子结构
|
7月前
【一刷《剑指Offer》】面试题 17:合并两个排序的链表
【一刷《剑指Offer》】面试题 17:合并两个排序的链表

热门文章

最新文章