【剑指Offer】对称的二叉树
题目描述
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
递归思路与代码
用递归的话咱们需要增加一个递归函数bool IsSym(TreeNode* lef, TreeNode* rig) ;
首先考虑出口:
(1)当lef 与rig都等于空的时候,返回true,说明二叉树搜索完了;
(2)当lef与rig只有一个是空,另外一个非空,或者lef与rig的val值不相等,都返回false,说明不对称。
下来考虑调用
(3)IsSym(lef->left, rig->right) && IsSym(lef->right, rig->left);记住要一对一对调用。左左对右右,左右对右左。
代码:
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
class Solution {
public:
bool IsSym(TreeNode* lef, TreeNode* rig) {
if (lef == nullptr && rig == nullptr&&lef->val==rig->val)//出口(1)
return true;
if ((lef == nullptr && rig != nullptr) || (lef != nullptr && rig == nullptr)
|| lef->val != rig->val)//出口(2)
return false;
return IsSym(lef->left, rig->right) && IsSym(lef->right, rig->left);
}
bool isSymmetrical(TreeNode* pRoot)
{
if (pRoot == nullptr)
return true;
return IsSym(pRoot->left, pRoot->right);
}
};
非递归思路与代码
非递归有两种,第一种队列实现非递归。
队列实现非递归
给队列中每次压入成对的节点:
当队列不为空的时候
(1)若队列不为空,成对的提取和弹出。
(2)若该对lef和rig都为空,则不再压入,直接进行continue。下面这种时候出现这种情况
(3)当lef与rig只有一个是空,另外一个非空,或者lef与rig的val值不相等,都返回false,说明不对称。
下来考虑调用
(4)继续进行成对的压入左左对右右,左右对右左。
注:用队列实现,是一层一层来遍历判断的。属于BFS(广/宽度优先搜索)。
代码:
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
if (pRoot == nullptr)
return true;
queue< TreeNode*> myq;
myq.push(pRoot->left);
myq.push(pRoot->right);
while (!myq.empty()) {
TreeNode* lef = myq.front();
myq.pop();
TreeNode* rig = myq.front();
myq.pop();
if (lef == nullptr && rig == nullptr)
continue;
if ((lef == nullptr && rig != nullptr) || (lef != nullptr && rig == nullptr)
|| lef->val != rig->val)
return false;
myq.push(lef->left);
myq.push(rig->right);
myq.push(lef->right);
myq.push(rig->left);
}
return true;
}
};
栈实现非递归
给栈中每次压入成对的节点:
当栈不为空的时候
(1)若栈不为空,成对的提取和弹出。
(2)若该对lef和rig都为空,则不再压入,直接进行continue。
(3)当lef与rig只有一个是空,另外一个非空,或者lef与rig的val值不相等,都返回false,说明不对称。
下来考虑调用
(4)继续进行成对的压入左左对右右,左右对右左。
注:用栈实现,是一个支路一个支路来遍历判断的。属于DFS(广/宽度优先搜索)。
代码与队列实现的方式除了一个使用queue装,下面这个使用stack 装之外,其他代码都一样。
注:但是认真画一下二叉树看一下怎么比较判断的。这两个实现方式在比较判断的节点顺序上完全不同。
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
if (pRoot == nullptr)
return true;
stack< TreeNode*> mys;
mys.push(pRoot->left);
mys.push(pRoot->right);
while (!mys.empty()) {
TreeNode* lef = mys.top();
mys.pop();
TreeNode* rig = mys.top();
mys.pop();
if (lef == nullptr && rig == nullptr)
continue;
if ((lef == nullptr && rig != nullptr) || (lef != nullptr && rig == nullptr)
|| lef->val != rig->val)
return false;
mys.push(lef->left);
mys.push(rig->right);
mys.push(lef->right);
mys.push(rig->left);
}
return true;
}
};
推荐阅读
-
《剑指offer》面试题6 重建二叉树
-
剑指offer25:复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),结果返回复制后复杂链表的head。
-
剑指offer31:整数中1出现的次数(从1到n整数中1出现的次数)
-
剑指offer28:找出数组中超过一半的数字。
-
剑指offer27:按字典序打印出该字符串中字符的所有排列
-
C#版剑指Offer-001二维数组中的查找
-
剑指offer11:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。(进制转换,补码反码)
-
剑指offer13:数组[奇数,偶数],奇数偶数相对位置不变。
-
剑指offer第二天
-
剑指offer JZ31 整数中1出现的次数 Python 解