题目地址:力扣
树对称,则说明从根往下走,根的左孩子的情况和根的右孩子情况相同(即要空都是空,不空的话值一定相等),根左孩子的左孩子情况与根右孩子的右孩子情况相同。
解法1:迭代法
思路:很容易想到的是树的层次遍历,因此需要队列。可以用一个队列存左子树的情况,一个队列存右子树的情况,然后比较即可。但是想一想,也可以不需要两个队列,一个队列就能搞定,只要依次序交叉存左孩子和右孩子的情况即可。那么在比较的时候,一次弹出两个元素就可以了。
这里需要注意的是初始情况和树只有一个节点的情况,为了适应减少判断,我们的队列也可以存空指针,空指针和空指针相等显然没有问题。初始的时候我们就在队列中存两次根节点就好了
class Solution {
public:
bool isSymmetric(TreeNode* root) {
queue<TreeNode *> que;
// 初始的时候存两次根节点
que.push(root), que.push(root);
// 只要队列不空
while(!que.empty())
{
// 取出队列中相邻的两个节点
TreeNode *node_1 = que.front();
que.pop();
TreeNode *node_2 = que.front();
que.pop();
// 这里对应着两个节点都是空指针的情况,就跳过本轮循环
if (!node_1 && !node_2)
continue;
// 这里前面判断的是是否存在两个指针中一个为空的情况
// 后面是在确定了两个指针都不为空的情况下,判断其值是否相等
if ((!node_1 || !node_2) || (node_1->val != node_2->val))
return false;
// 为了验证对称性,左节点的左孩子后面跟着右节点的右孩子
que.push(node_1->left);
que.push(node_2->right);
// 为了验证对称性,左节点的右孩子后面跟着右节点的左孩子
que.push(node_1->right);
que.push(node_2->left);
}
return true;
}
};
解法2:递归法
思路:因为要判断左子树和右子树是否对称,那么递归的话就需要传入两个指针才够。边界条件和迭代的方法是一样的,递归就只需要考虑当前层需要做的事情,当前层除了满足边界条件return之外,如果不满足边界条件就检查左边节点的的左孩子与右边节点的右孩子是否等,检查右边节点的左孩子与左边节点的右孩子是否等,返回两者与的结果。这样递归,左边节点和右边节点永远都在同一层
class Solution {
public:
bool check(TreeNode* l, TreeNode *r)
{
// 均为空
if (!l && !r)
return true;
// 一空一不空,或者都不空但值不相等
else if ((!l || !r) || l->val != r->val)
return false;
// 都不空且值相等,检查l的左与r的右是否等,检查r的左与l的右是否等,返回两者与的结果
else
return (check(l->left, r->right) && check(l->right, r->left));
}
bool isSymmetric(TreeNode* root) {
return check(root, root);
}
};
Accepted
- 198/198 cases passed (0 ms)
- Your runtime beats 100 % of cpp submissions
- Your memory usage beats 48.25 % of cpp submissions (16 MB)