刚又刷了一道难度适中的题目,下面就和大家分享一下经验。
题目如下:
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.
题意分析:
给定一个二叉树,请判断它是否镜像对称。你可以用递归法或者迭代法解决该问题。
方法一(递归法DFS)
采用深度优先搜索DFS,首先将给定的二叉树分成左右两个子树,这样就可以把问题转换成比较两个二叉树是否镜像对称了,思路与“https://blog.csdn.net/Vensmallzeng/article/details/94960252”相似,只是在递归调用时需要将左右子树换个位,如果不镜像对称则返回false,否则镜像对称返回True。
解题代码如下:
class Solution{
public:
bool isSymmetric(TreeNode* root){
if (!root) return true;
//将一个二叉树分成左右两个子树
return isSymmetric(root->left, root->right);
}
//将左右两个子树分别看做一个二叉树,然后自定义一个函数判断是否镜像对称
bool isSymmetric(TreeNode* left, TreeNode* right){
if(!left && !right) return true;
if((!left && right) || (left && !right) || (left->val != right->val)) return false;
return isSymmetric(left->left, right->right) && isSymmetric(left-> right, right-> left);
}
};
提交后的结果如下:
方法二(迭代法)
新建两个队列q1、q2,首先判断root节点是否为空,如果为空则直接返回true,否则将root的左右两个子结点(root->left、root->right)分别存入两个队列,然后开始while循环,循环条件为两个队列都不为空。在while循环中,首先分别将两个队列中的队首元素取出来,如果两个元素都是空结点,那么直接continue跳过(因为有可能某个结点没有左子结点但是右子结点仍然存在)。紧接着,如果有一个元素为空,另一个元素不为空,那么此时已经不对称了直接返回false。若两个元素都存在,但是其值不同,此时也已经不对称了直接返回false。否则将root->left的左、右子结点排入q1,同时将root->right的右、左子结点排入q2。最后,由于循环结束后两个队列一定均为空,所以不必再去判断两个队列是否同时为空,其他情况比如一空一不空的直接在循环内部就返回false了,故当循环结束后直接返回true即可。
注:以下四句之前不应该加判断是否为空,因为对于“[1,2,2,null,3,null,3]”这个例子,如果排除了空的情况,队列中最终存的结果会导致误判。
q1.push(temp1->left);
q1.push(temp1->right);
q2.push(temp2->right);
q2.push(temp2->left);
解题代码如下:
class Solution{
public:
bool isSymmetric(TreeNode* root){
if(!root) return true;
queue<TreeNode*> q1, q2;
q1.push(root->left);
q2.push(root->right);
while(!q1.empty() && !q2.empty()){
TreeNode* temp1 = q1.front();
q1.pop();
TreeNode* temp2 = q2.front();
q2.pop();
if(!temp1 && !temp2) continue;
if((!temp1 && temp2) || (temp1 && !temp2) || (temp1->val != temp2->val)) return false;
q1.push(temp1->left);
q1.push(temp1->right);
q2.push(temp2->right);
q2.push(temp2->left);
}
return true;
}
};
提交后的结果如下:
方法三(堆栈法DFS)
在“https://blog.csdn.net/Vensmallzeng/article/details/94960252”中方法二的基础上进行改进。
解题代码如下:
注:为了有利于后面比较size,所以需要加判断是否为空。
if(temp1->right) s1.push(temp1->right);
if(temp2->left) s2.push(temp2->left);
//若两个二叉树的结构不同则返回false
if (s1.size() != s2.size()) return false;
if(temp1->left) s1.push(temp1->left);
if(temp2->right) s2.push(temp2->right);
//若两个二叉树的结构不同则返回false
if (s1.size() != s2.size()) return false;
以下四句之前不应该加判断是否为空,因为对于“[1,2,2,null,3,null,3]”这个例子,如果排除了空的情况,队列中最终存的结果会导致误判。
class Solution{
public:
bool isSymmetric(TreeNode* root){
stack<TreeNode*> s1, s2;
if (!root) return true;
if(root-> left) s1.push(root-> left);
if(root-> right) s2.push(root-> right);
while ( !s1.empty() && !s2.empty() ){
TreeNode* temp1 = s1.top();
s1.pop();
TreeNode* temp2 = s2.top();
s2.pop();
//若两个二叉树的对应节点值不同则返回false
if (temp1->val != temp2-> val) return false;
//在保存节点的左右子节点之前,判断左右子节点是否为空,有利于后面比较size
if(temp1->right) s1.push(temp1->right);
if(temp2->left) s2.push(temp2->left);
//若两个二叉树的结构不同则返回false
if (s1.size() != s2.size()) return false;
if(temp1->left) s1.push(temp1->left);
if(temp2->right) s2.push(temp2->right);
//若两个二叉树的结构不同则返回false
if (s1.size() != s2.size()) return false;
}
return s1.size() == s2.size();
}
};
提交后的结果如下:
日积月累,与君共进,增增小结,未完待续。