对称二叉树问题的具体思路 递归法 迭代法 (附完整代码)


前言

本文将围绕以下问题展开讨论

如何求解对称二叉树问题(检验一个二叉树的左右两侧是否是轴对称的)?

本文将采用两种方法 【递归】【迭代】解决此问题(文章末尾附完整代码)


一、如何理解对称二叉树

题目链接:[点击跳转] 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)。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值