【LeetCode】Symmetric Tree(对称二叉树)

这道题是LeetCode里的第101道题。是我在学数据结构——二叉树的时候碰见的题。

题目如下:

给定一个二叉树,检查它是否是镜像对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

     1
   /   \
  2     2
 / \   / \
3   4 4   3

但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:

    1
   / \
  2   2
   \   \
    3   3

说明:

你可以运用递归和迭代两种方法解决这个问题。

解题思路:

读完题目后我首先想到的是用遍历的方法来解题,树的遍历有三种:前序遍历,中序遍历和后序遍历。

这里我选择的是中序遍历,对根节点的左右子树分别进行中序遍历,但是因为要符合题目的要求——对称,所以两种中序遍历的方式不一样,根节点左子树采用LDR中序遍历,根节点右子树采用RDL中序遍历。

如同上面的两个示例:第一颗树根节点的左子树遍历结果是[3,2,4],而根节点的右子树遍历结果是[3,2,4],相等。对称。

第二颗树根节点的左子树遍历结果是[2,3],而根节点的右子树遍历结果是[3,2],不相等。不对称。

代码如下: 

 1 /**
 2  * Definition for a binary tree node.
 3  * struct TreeNode {
 4  *     int val;
 5  *     TreeNode *left;
 6  *     TreeNode *right;
 7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 8  * };
 9  */
10 class Solution {
11 public:
12     vector<int> LPreOrder(TreeNode* tree){//LDR中序遍历
13         stack<TreeNode*>st;//节点堆栈
14         vector<int>res;
15         TreeNode* pt;
16         if(tree==NULL)return res;
17         pt=tree;
18         while(pt!=NULL||st.size()!=0){
19             while(pt!=NULL){//先访问左节点
20                 st.push(pt);
21                 pt=pt->left;
22             }
23             pt=st.top();//最下边的左节点
24             res.push_back(pt->val);//保存数值
25             st.pop();
26             pt=pt->right;//访问右节点
27         }
28         return res;
29     }
30     vector<int> RPreOrder(TreeNode* tree){//RDL中序遍历
31         stack<TreeNode*>st;
32         vector<int>res;
33         TreeNode* pt;
34         if(tree==NULL)return res;
35         pt=tree;
36         while(pt!=NULL||st.size()!=0){
37             while(pt!=NULL){
38                 st.push(pt);
39                 pt=pt->right;
40             }
41             pt=st.top();
42             res.push_back(pt->val);
43             st.pop();
44             pt=pt->left;
45         }
46         return res;
47     }
48     bool isSymmetric(TreeNode* root) {
49         if(root==NULL)//根节点是否为空
50             return true;
51         if(root->left==NULL||root->right==NULL){//左右子树其中一个是否为空
52             if(root->left==NULL&&root->right==NULL)//左右子树是否为空
53                 return true;
54             return false;
55         }
56         else{
57             if(root->left->val!=root->right->val)return false;
58             vector<int>Lorder,Rorder;
59             Lorder=LPreOrder(root->left);//遍历
60             Rorder=RPreOrder(root->right);//遍历
61             if(Lorder!=Rorder)return false;//判断遍历结果是否相同
62             return true;
63         }
64     }
65 };

运行结果:

测试结果通过。。。

这其实这还没结束,因为如果是这颗树的话(自己突然想到的):

很明显不对称是不是,但是仍然能通过测试,就说明在测试案例里没有这颗树。钻了个空子。

然后我没办法只好用官方解题思路:

就是使用双节点递归对每一个节点及其相对称的节点进行左右对称判断。类似于广度优先算法,或是层次遍历。

 1 /**
 2  * Definition for a binary tree node.
 3  * struct TreeNode {
 4  *     int val;
 5  *     TreeNode *left;
 6  *     TreeNode *right;
 7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 8  * };
 9  */
10 class Solution {
11 public:
12     bool isMirror(TreeNode* t1,TreeNode* t2){
13         if(t1==NULL&&t2==NULL)return true;
14         if(t1==NULL||t2==NULL)return false;
15         return (t1->val==t2->val)
16             &&isMirror(t1->left,t2->right)
17             &&isMirror(t2->left,t1->right);
18     }
19     bool isSymmetric(TreeNode* root) {
20         return isMirror(root,root);
21     }
22 };

是不是看起了简单多了?我也学习到了。

个人总结:写算法不能只光顾一个案例,要善于使用各种特殊的案例来测试算法的正确性和可行性,在这里我就是在编写过程中没有充分考虑到空节点的情况,导致了多次提交的错误。

posted @ 2018-11-24 14:06 1000sakura 阅读(...) 评论(...) 编辑 收藏