前言
本文将围绕以下问题展开讨论
如何求解对称二叉树问题(检验一个二叉树的左右两侧是否是轴对称的)?
本文将采用两种方法 【递归】【迭代】解决此问题(文章末尾附完整代码)
一、如何理解对称二叉树
题目链接:[点击跳转] Leetcode 101. 对称二叉树
如下是具体题目要求:
仔细分析题目后我们发现,一个对称的二叉树,需要满足几个条件:
1.结构对称,如果一个树中只有一个节点,或者是一个空树,那么也应该是对称的。
2.对应节点元素相等。
所以只要满足上述的要求,我们就可以解决这道题啦!
二、方法一(递归法)
这道题的本质是检验一个二叉树是否是对称的,那么毋庸置疑,核心内容应该是不断的去做一个比对、对照,去判断是否满足前面提到的两个条件。
我们首先定义一个函数isSymmetric,通过传入根节点,就可以判断true/false。
bool isSymmetric(TreeNode* root) {
return ;
}
现在我们该考虑如何在只给出根节点的情况下,判断子节点的对称性?于是,我们想到了递归法,定义一个递归函数,传入根节点左右两侧的子节点,返回true or false。
bool digui(TreeNode* A,TreeNode* B){
return //true or false
}
如果传入的两个子节点为空呢?
那么我们就直接返回true,因为两侧都是空的,也是对称的一种形式呀!
bool digui(TreeNode* A,TreeNode* B){
if(A==nullptr&&B==nullptr){
return true;
}
return //true or false
}
如果传入的两个子节点中只有一个为空呢?
那么我们返回false。
bool digui(TreeNode* A,TreeNode* B){
if(A==nullptr&&B==nullptr){
return true;
}
else if((A==nullptr&&B!=nullptr)||(B==nullptr&&A!=nullptr)){
return false;
}
return //true or false
}
好了,到这里时我们已经解决了结构对称的问题,接下来需要考虑传入的这两个节点是否相等,以及这两个节点下面的节点又是否对称。
如果传入的这两个节点相等,并且它们的子树还对称,那么就可以认为这是一个对称二叉树了。
bool digui(TreeNode* A,TreeNode* B){
if(A==nullptr&&B==nullptr){
return true;
}
else if((A==nullptr&&B!=nullptr)||(B==nullptr&&A!=nullptr)){
return false;
}
if((A->val==B->val)&&(digui(A->left,B->right)&&digui(A->right,B->left))){
return true;
}
return false;
}
完整代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool digui(TreeNode* A,TreeNode* B){
if(A==nullptr&&B==nullptr){
return true;
}
else if((A==nullptr&&B!=nullptr)||(B==nullptr&&A!=nullptr)){
return false;
}
if((A->val==B->val)&&(digui(A->left,B->right)&&digui(A->right,B->left))){
return true;
}
return false;
}
bool isSymmetric(TreeNode* root) {
return digui(root->left,root->right);
}
};
时间复杂度为O(n)。
三、方法二(迭代法)
当然,我们也可以不选择递归的方法来解决这个问题,但不使用递归的情况下,我们又该如何将二叉树的所有节点全部做一次对称性检验呢?
这里我们选择借助栈,来完成对所有节点进行一遍储存,这样我们就不需要用递归的方式走完所有节点了。
那么重点来了,该怎样储存?储存后又该如何检验呢?
首先,我们定义函数diedai,通过传入根节点,返回true or false,再定义一个栈sta用来存节点。
stack<TreeNode*> sta;
bool diedai(TreeNode* root){
return;
}
接下来就可以将根节点下的左右子节点压入栈中啦
stack<TreeNode*> sta;
bool diedai(TreeNode* root){
TreeNode* L=root->left;
TreeNode* R=root->right;
sta.push(L);
sta.push(R);
return ;
}
压入栈中后就需要,对这两个节点做一个判断啦
观察下面这个二叉树,当我们把 节点1 传入函数后,会将 左子节点2 和 右子节点 压入栈中。
如果 这个左2==右2,那么就继续将 左2 下面的 左3 和 右2 下的 右3 压入栈,再将 左2 下面的 右4 和 右2 下面的 左4 压入栈。
如果前两数相等,并且后两个数也相等,说明对称。
因此我们可以写出如下代码:
stack<TreeNode*> sta;
bool diedai(TreeNode* root){
TreeNode* L=root->left;
TreeNode* R=root->right;
sta.push(L);
sta.push(R);
while(!sta.empty()){
L=sta.top();
sta.pop();
R=sta.top();
sta.pop();
if(!L&&!R){
continue;
}
if((!L || !R) || (L->val != R->val)){
return false;
}
sta.push(L->left);
sta.push(R->right);
sta.push(L->right);
sta.push(R->left);
}
return true;
}
上述代码中压入栈后,也要记得出栈,否则节点将会一直留在栈顶
完整代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
stack<TreeNode*> sta;
bool diedai(TreeNode* root){
TreeNode* L=root->left;
TreeNode* R=root->right;
sta.push(L);
sta.push(R);
while(!sta.empty()){
L=sta.top();
sta.pop();
R=sta.top();
sta.pop();
if(!L&&!R){
continue;
}
if((!L || !R) || (L->val != R->val)){
return false;
}
sta.push(L->left);
sta.push(R->right);
sta.push(L->right);
sta.push(R->left);
}
return true;
}
bool isSymmetric(TreeNode* root) {
return diedai(root);
}
};
时间复杂度为O(n)。