剑值offer面试题28——对称的二叉树

题目:请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。例如下图中,第一棵二叉树是对称的,另外两棵不是。

思路:

       这道题我开始想的是,先求出二叉树的镜像然后进行对比,比较两棵二叉树是否相同。理论上是可行的,但是过程会繁琐一点。书中给了一种思路:先对二叉树进行前序遍历,比如上面第一棵二叉树前序序列为8657675,再自定义一种前序遍历的方式,每次遍历一个节点之后,先遍历一个节点的右节点,再遍历节点的左节点。比如上面第一棵树的自定义前序序列为8657675,两个序列一样说明,这个二叉树为对称二叉树。但是再看看第三棵树,发现两种遍历的序列都是777777,但是这棵树不是对称的二叉树,那么怎么解决这个问题呢?可以把所有的叶子节点处都补上缺失的左右孩子(nullptr),这样再对第三棵树进行前序遍历的结果就是{7 7 7 nullptr nullptr 7 nullptr nullptr  7  7 nullptr nullptr nullptr};自定义前序遍历的结果为{7 7 nullptr 7 nullptr nullptr 7 7 nullptr nullptr 7 nullptr nullptr},可以看出来这两个序列是不相等的。下面代码的函数重载操作很有意思,这样就可以实现两个序列同步的遍历和比较。还是老问题,要注意输入的节点为空等问题,保证代码的鲁棒性。

代码:

struct BinaryTreeNode
{
	double  m_dbValue;
	BinaryTreeNode*  m_pLeft;
	BinaryTreeNode* m_pRight;
};


bool isSymmetrical(BinaryTreeNode* pRoot)//函数重载
{
	return isSymmetrical(pRoot, pRoot);
}

bool isSymmetrical(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
	if (pRoot1 == nullptr&&pRoot2 == nullptr)
		return true;//递归边界,将叶子节点添加了两个nullptr节点,同时可以处理只有一个节点的树的情况
	if (pRoot1 == nullptr || pRoot2 == nullptr)
		return false;//对应位置,一个节点存在,一个节点不存在,该二叉树肯定就不镜像相等
	if (pRoot1->m_dbValue != pRoot2->m_dbValue)
		return false;
	return isSymmetrical(pRoot1->m_pLeft, pRoot2->m_pRight) && isSymmetrical(pRoot1->m_pRight, pRoot2->m_pLeft);
}

复习:

很棒的递归思路,特别是最后的return的返回值,代码非常简洁。

二刷代码:

struct  BinaryTreeNode
{
	int m_Value;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_pRight;
};

bool isSymmetrical(BinaryTreeNode* pRoot)
{
	return isSymmetrical(pRoot, pRoot);
}

bool isSymmetrical(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
	if (pRoot1 == nullptr&&pRoot2 == nullptr)
		return true;
	if (pRoot1 == nullptr || pRoot2 == nullptr)
		return false;
	if (pRoot1->m_Value != pRoot2->m_Value)
		return false;
	
	return isSymmetrical(pRoot1->m_pLeft, pRoot2->m_pRight) &&
		isSymmetrical(pRoot1->m_pRight, pRoot2->m_pLeft);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值