Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
For example, this binary tree [1,2,2,3,4,4,3] is symmetric:
1
/ \
2 2
/ \ / \
3 4 4 3
But the following [1,2,2,null,3,null,3] is not:
1
/ \
2 2
\ \
3 3
Note:
Bonus points if you could solve it both recursively and iteratively.
思路:首先题意对称树是指沿着根节点对折,两边子树节点上对应的数值完全相等。看到二叉树,不知道大家什么想法,我一想二叉树不是常考先序,中序,后序遍历之类的吗?看看这题怎么用先序遍历做吧?
比如例子中给的这个输入
1
/ \
2 2
/ \ / \
3 4 4 3
做一次先序遍历(先序遍历顺序为根->左子树->右子树) 得到:1,2,3,4,2,4,3
然后怎么判断是否是镜像呢?既然是镜像,那我按照镜像先序遍历的路线(根->右子树->左子树) 再遍历一遍树,也能得到一个序列啊,这样看看这两个序列是否相等就可以知道这棵树是不是对称树了啊!于是上面树的镜像先序遍历为1,2,3,4,2,4,3
,似乎这个方法是可行的。
再看看题目中给的不是对称树的输入情况。比如输入如下:
1
/ \
2 2
\ \
3 3
先序遍历(根->左->右):1,2,3,2,3
镜像先序遍历(根->右->左):1,2,3,2,3
,等等,竟然一样???其实深入分析就知道,在遍历的过程中,是因为有的节点只有一边有孩子,另一边为null造成的,如果我们把每个节点的左右孩子为null也加入遍历的序列中,可以得到:
先序遍历:1,2,null,3,null,null,2,null,3,null,null
镜像先序遍历:1,2,3,null,null,null,2,null,3,null,null
可以看到,加入null可以成功区分这种情况,当然第一种情况下也必然可以适用!
1
/ \
2 2
/ \ / \
3 4 4 3
先序遍历(根->左->右):1,2,3,null,null,4,null,null,2,4,null.null,3,null,null
镜像先序遍历(根->右->左):1,2,3,null,null,4,null,null,2,4,null,null,3,null,null
以下C++递归实现:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
preOrderTraverse(root, ans1);//
preOrderTraverse1(root, ans2);
//cout<<ans1<<endl;
//cout<<ans2<<endl;
return ans1 == ans2;
}
void preOrderTraverse(TreeNode* root, string& ans){//先序遍历
if(root == NULL){
ans += "NULL";
return;
}
ans += to_string(root->val);
preOrderTraverse(root->left, ans);//先序遍历根->左->右
preOrderTraverse(root->right, ans);
}
void preOrderTraverse1(TreeNode* root, string& ans){//镜像先序遍历
if(root == NULL){
ans += "NULL";
return;
}
ans += to_string(root->val);
preOrderTraverse1(root->right, ans);//根->右->左
preOrderTraverse1(root->left, ans);
}
string ans1;//存放preOrderTraverse遍历的结果
string ans2;//存放preOrderTraverse1遍历的结果
};
结果:遍历了两次树,还有两个string存储遍历结果,效果不是最好的,但是我感觉我这个思路算是比较简单,自己还是可以接收。。。。
C++非递归版:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
preOrderTraverse(root, ans1);//
//cout<<ans1<<endl;
preOrderTraverse1(root, ans2);
//cout<<ans2<<endl;
return ans1 == ans2;
}
void preOrderTraverse(TreeNode* root, string& ans){
if(root == NULL)
return;
stack<TreeNode *> stk;
while(root || !stk.empty()){//end condition p==NULL, and stk is empty
if(root){
stk.push(root);
ans += to_string(root->val);
root = root->left;
}
else{//到了最左边
ans += "NULL";//此时root=NULL
root = stk.top();
stk.pop();
root = root->right;
}
}
}
void preOrderTraverse1(TreeNode* root, string& ans){
if(root == NULL)
return;
stack<TreeNode *> stk;
while(root || !stk.empty()){//end condition p==NULL, and stk is empty
if(root){
stk.push(root);
ans += to_string(root->val);
root = root->right;
}
else{//到了最右边,已经访问玩最后一个节点的根节点和右节点,下一步访问左节点
ans += "NULL";//此时root=NULL
root = stk.top();
stk.pop();
root = root->left;
}
}
}
string ans1;//存放preOrderTraverse遍历的结果
string ans2;//存放preOrderTraverse1遍历的结果
};
速度竟然比递归版本还慢,有点不理解。
python递归版本:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def __init__(self):
self.ans1 = ''
self.ans2 = ''
def isSymmetric(self, root):
"""
:type root: TreeNode
:rtype: bool
"""
self.preOrderTraverse(root)
self.preOrderTraverse1(root)
return self.ans1 == self.ans2
def preOrderTraverse(self, TreeNode):
if TreeNode == None:
self.ans1 += "NULL"
return;
self.ans1 += str(TreeNode.val)
self.preOrderTraverse(TreeNode.left)
self.preOrderTraverse(TreeNode.right)
def preOrderTraverse1(self, TreeNode):
if TreeNode == None:
self.ans2 += "NULL"
return;
self.ans2 += str(TreeNode.val)
self.preOrderTraverse1(TreeNode.right)
self.preOrderTraverse1(TreeNode.left)
速度貌似不是很理想。非递归版本和C++的实现一样,就不写了。