LeetCode 101. Symmetric Tree(判断是否是对称树,C++, Python,递归与非递归做法)

101. Symmetric Tree

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++的实现一样,就不写了。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值