Technology Sharing

Algorithm Likou question record 42 [101. Symmetric binary tree, 100. The same tree, 572. The subtree of another tree]

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Preface

Binary tree chapter, start practicing binary tree operations.
Record forty-two [101. Symmetric binary tree].
continue.


1. Read the topic

Given a binary tree root, Check if it is axisymmetric

Example 1:
insert image description here

输入:root = [1,2,2,3,4,4,3]
输出:true
  • 1
  • 2

Example 2:
insert image description here

输入:root = [1,2,2,null,3,null,3]
输出:false
  • 1
  • 2

hint:

树中节点数目在范围 [1, 1000] 内
-100 <= Node.val <= 100
  • 1
  • 2

Advanced: You can useRecursion and IterationAre there two ways to solve this problem?


2. Try to achieve

Idea 1

Let’s try it with recursion first. Core: What is the criterion for determining axial symmetry?

Recursion: calling itself.No duplicate logic has been found yet

  • Check left== right? Enter the subtree, which is incorrect.
  • The left subtree goes to the left-right-center, and the right subtree goes to the right-left-center. Are the sequences equal? ​​But this is true for the entire tree. Entering the subtree is also wrong.

Idea 2

Change the iterative method to use level-order traversal.
After obtaining the layer sequence result, we determine whether each layer is an even number and is equal after reverse. However, this is not true for Example 2 because the null pointer is excluded.
The idea doesn't work.

Summarize:Although we know that we need to find symmetry, we don’t know how to unify the criteria for judging symmetry.


3. Reference ideas

Reference link

Learning Content

  • Axis symmetry: Can the left and right subtrees of the root node be flipped to be equal? , how to compare?
  • Obtained from the explanationCorrect thinking:This traversal requires the left subtree of the root node and the right subtree of the root nodeSimultaneous traversalOnly by traversing two subtrees at once can we determine whether the nodes on both sides are equal.
    • First, pass the left of the left subtree and the right of the right subtree. At this time, the outer nodes are judged to be equal;
    • Then pass the right of the left subtree and the left of the right subtree, and the inner nodes are judged to be equal;
    • After both are returned, they are both true at the same time, indicating symmetry.
  • Determine the traversal order: left, right, middle. After processing the left child, process the right child and return the result to the middle node.
  • Trying to implementInsufficient ideas:Only process the left subtree of the root node, and find that the order of the right subtree of the root node is different from that of the left. Reversing the traversal order or doing anything else will not give a unified logic.

Recursive implementation

Every comment is an idea.

/**
 * 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 iscompare(TreeNode* left,TreeNode* right){ //两边同时遍历,所以两个参数。返回是否相等,用bool类型。
        //确定终止条件
        if(!left && !right) return true;    //同时为空,可以翻转
        else if(!left && right) return false; //一个空,一个不为空。肯定不等
        else if (!right && left) return false;//一个空,一个不为空。肯定不等
        else if(left->val != right->val) return false;//都不为空,但是值不等

        //都不为空,值相等。说明可以继续进行外侧比较、内侧比较,不用return。
        bool outside = iscompare(left->left,right->right);  //同时比较,解决了左右遍历顺序不一样
        bool inside = iscompare(left->right,right->left);
        return outside && inside;   //同时返回true。才能返回true
    }
    bool isSymmetric(TreeNode* root) {
        return iscompare(root->left,root->right);
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

The traversal order of a tree (left subtree) is left-right-middle, and the traversal order of a tree (right subtree) is right-left-middle.

Iteration Idea 1

  • Process the left subtree and the right subtree of the root node at the same time. It is different from the previous traversal.
  • Use queue structure:The two nodes to be compared are placed in the queue at the same time,AgainTake out at the same time. Determine whether the two nodes taken out can be flipped. So if the left and right children are free, they also need to be put in the queue.
  • Using a stack structure: You still need to process two nodes at the same time. There are two objects to be compared. Put them in at the same time, and take them out at the same time

Iterative implementation [queue structure]

The stack structure is the same.

/**
 * 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 isSymmetric(TreeNode* root) {
        if(!root) return false;
        queue<TreeNode*> que;
        que.push(root->left);//放入左子树
        que.push(root->right);//放入右子树
        while(!que.empty()){
            TreeNode* left = que.front(); que.pop();//取出比较对象中的左节点
            TreeNode* right = que.front();que.pop();//取出比较对象中的右节点

            if(!left && !right){    //都是空节点
                continue;
            }else if(!left || !right || left->val != right->val){
                return false;
            }

            que.push(left->left);
            que.push(right->right);
            que.push(left->right);
            que.push(right->left);
        }
        return true;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

Summary [Axisymmetric binary tree]:

  • It is still traversal, the difference is:Both subtrees must be traversed simultaneouslyIt is wrong to recurse deep into any subtree.
  • The conditions for comparing objects to judge true: both are empty; or the values ​​are equal. The rest are false.
  • It is also not possible to recursively traverse any subtree because the order of the left and right sides is different.
  • It is not a layer-order traversal. If you must use a layer-order traversal: get the result of each layer, reverse it and see if it is equal. As follows (not recommended), the above solutions are all good.
/**
 * 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 isSymmetric(TreeNode* root) {
        vector<vector<int>> level;
        queue<TreeNode*> que;
        if(!root) return false;
        que.push(root);
        while(!que.empty()){
            int size = que.size();
            vector<int> vec;
            while(size--){
                TreeNode* cur = que.front();que.pop();
                if(cur){ //不是空节点
                    que.push(cur->left);
                    que.push(cur->right);
                    vec.push_back(cur->val);
                }else{
                    vec.push_back(INT_MIN);//因为节点的值【-100,100】。用一个最小值代表空。
                }
            }
            level.push_back(vec);
        }
        //获得层序遍历。包含空。空的数值借助INT_MIN代替。
        for(int i = 1;i < level.size();i++){
            vector<int> temp = level[i];
            reverse(temp.begin(),temp.end());
            if(temp != level[i]){
                return false;
            }
        }
        return true;

    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

Exercises

100. The same tree

1. Title

Given two binary trees with roots p and q, write a function to test whether the two trees are identical.

If two treesAre structurally identical and the nodes have the same values, they are considered to be the same.

Example 1:

输入:p = [1,2,3], q = [1,2,3]
输出:true
  • 1
  • 2

Example 2:

输入:p = [1,2], q = [1,null,2]
输出:false
  • 1
  • 2

Example 3:

输入:p = [1,2,1], q = [1,1,2]
输出:false
  • 1
  • 2

hint:

两棵树上的节点数目都在范围 [0, 100] 内
-10^4 <= Node.val <= 10^4
  • 1
  • 2

Ideas

Determine whether two trees are identical. They have the same structure and the same values.

  • Then you mustProcessing two trees at the same time, there is a comparison object. It is useless to just traverse a tree deeply/do anything.
  • The difference from [101. Symmetric Binary Tree] is the comparison object. HereComparison objects: left child and left child; right child and right child. The parameters of the recursive call are given.

Code

/**
 * 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 isSameTree(TreeNode* p, TreeNode* q) {
        if(!p && !q) return true;  //传入节点同时为空,可以对应
        else if(!p && q) return false;//一个空,另一个不是空。不可能对应。
        else if(p && !q) return false;//一个空,另一个不是空。不可能对应。
        else if(p->val != q->val) return false;//值不等,不可能对应。

        bool leftchild = isSameTree(p->left,q->left); 
        bool rightchild = isSameTree(p->right,q->right);
        return leftchild && rightchild;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

["572. Subtree of another tree"]

topic

Given two binary trees root and subRoot. Check whether root contains the same tree as subRoot.Same structure and node valuesIf the subtree exists, return true; otherwise, return false.

A subtree of a binary tree tree includes a node of tree and all the descendant nodes of this node. tree can also be regarded as a subtree of itself.

Example 1:

输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true
  • 1
  • 2

Example 2:

输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false
  • 1
  • 2

hint:

root 树上的节点数量范围是 [1, 2000]
subRoot 树上的节点数量范围是 [1, 1000]
-10^4 <= root.val <= 10^4
-10^4 <= subRoot.val <= 10^4
  • 1
  • 2
  • 3
  • 4

Ideas

(1) Subtrees also determine whether two trees are equal. You can use [Problem 100. Code Implementation] to solve the equality judgment.
(2) But it must be found in the rootEqual to the subRoot root node valueThe node is used as the root node of the subtree. Use level-order traversal to traverse the root.

Code

/**
 * 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 isSame(TreeNode* rootnode,TreeNode* subRootnode){
        if(!rootnode && !subRootnode) return true;
        else if(!rootnode && subRootnode) return false;
        else if(rootnode && !subRootnode) return false;
        else if(rootnode->val != subRootnode->val) return false;

        bool leftchild = isSame(rootnode->left,subRootnode->left);
        bool rightchild = isSame(rootnode->right,subRootnode->right);
        return leftchild && rightchild;
    }
    bool isSubtree(TreeNode* root, TreeNode* subRoot) {
        //先找到和subRoot值相等的节点,才有可能相等。得遍历root找到和subRoot值相等的节点,可能作为子树的根节点

        //用层序遍历
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()){
            int size = que.size();
            while(size--){
                TreeNode* cur = que.front();que.pop();
                if(cur->val == subRoot->val){
                    bool subtree = isSame(cur,subRoot);
                    if(subtree) return true;
                }
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
        }
        return false;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

Summary

Core: Traverse two trees at the same time to determine the comparison object. Implement recursion.

Going deep into any tree traversal will not yield both sides of the comparison object.

(Corrections are welcome, please indicate the source when reprinting)