Algorithmic customs clearance village - easily handle the double pointer in the binary tree

1. The same tree

Identical Trees
Given the root nodes p and q of two binary trees, write a function to check whether the two trees are identical.
Two trees are considered identical if they are structurally identical and the nodes have the same value.
Input: p = [1,2,3], q = [1,2,3]
Output: true

1.1 Depth First

It is necessary to judge whether the two binary trees are empty, and then judge whether one is empty, and then use the recursive comparison of the left subtree and the right subtree.

public boolean isSameTree(TreeNode p, TreeNode q) {
    
    
        // 两者都为空
        if(p == null && q==null) return true;
        // 两者有一个为空
        if(p==null || q == null) return false;

        if(p.val!=q.val){
    
    
            return false;
        }
        // 递归
        return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
    }

insert image description here
What needs to be noted here is that && is placed in front of ||. I didn’t pay attention at first, and I found out that the logic was wrong when I made a mistake.

1.2 Breadth First

Use the queue to store the binary tree elements, and then compare whether the values ​​of the two nodes are equal, exit directly if they are not equal, and continue to traverse the left subtree and the right subtree if they are equal.

public boolean isSameTree(TreeNode p, TreeNode q) {
    
    
        if(p==null && q == null) return true;
        if(p == null || q==null) return false;
        Queue<TreeNode> queue1 = new LinkedList<TreeNode>();
        Queue<TreeNode> queue2 = new LinkedList<TreeNode>();
      queue1.offer(p);
      queue2.offer(q);
      while(!queue1.isEmpty() && !queue2.isEmpty()){
    
    
          TreeNode node1=queue1.remove();
          TreeNode node2 = queue2.remove();
          if(node1.val!=node2.val){
    
    
              return false;
          }
          TreeNode left1 = node1.left,right1=node1.right;
          TreeNode left2 = node2.left,right2=node2.right;
          // 使用异或来判断是否有子节点
          if(left1==null ^ left2==null) return false;
          if(right1==null ^ right2==null) return false;
            
          if(left1!=null) queue1.offer(left1);
          if(right1!=null) queue1.offer(right1);
          if(left2!=null) queue2.offer(left2);
          if(right2!=null) queue2.offer(right2);
      }

      return queue1.isEmpty() && queue2.isEmpty();
    }

Although there are a lot of if statement judgments in this, it is not difficult to understand.

2. Symmetric binary tree

Symmetric Binary Tree
Given you a binary tree root node, check if it is axisymmetric.

2.1 Recursion

The main idea is to compare the left subtree and the right subtree of the subtree. Split a binary tree from the root node into two binary trees, similar to the first question, due to the symmetric nature, it is necessary to compare the left node of the first subtree with the right node of the second subtree, using recursive identification Still simple.

public boolean isSymmetric(TreeNode root) {
    
    
        if(root == null ) return true;
        return check(root.left,root.right);
    }

    public boolean check(TreeNode p,TreeNode q){
    
    
        if(p == null && q==null) return true;
        if(p==null || q ==null) return false;
        return p.val == q.val && check(p.left,q.right) && check(p.right,q.left);
    }

2.2 Iteration

It is also divided into two binary trees, but this time you only need to use one queue, and you can reach the left subtree or the right subtree according to the order in which the queues come out.

public boolean isSymmetric(TreeNode root) {
    
    
      if(root == null || (root.left==null && root.right==null)) return true;
      Queue<TreeNode> queue = new LinkedList<>();
      queue.add(root.left);
      queue.add(root.right);
      while(!queue.isEmpty()){
    
    
          TreeNode left = queue.remove();
          TreeNode right = queue.remove();
          if(left == null && right == null) continue;
          if(left==null || right==null) return false;
          if(left.val!=right.val) return false;
            // 左孩子的左节点和右孩子的右节点比较
          queue.add(left.left);
          queue.add(right.right);
          // 左节点的右孩子和右节点的左孩子放入队列
          queue.add(left.right);
          queue.add(right.left);
      }

      return true;
    }

insert image description here
But it is more time-consuming.

3. Merge binary trees

Merging binary trees
gives you two binary trees: root1 and root2.

Imagine that when you overlay one tree on top of the other, some nodes on both trees will overlap (and others won't). You need to merge these two trees into a new binary tree. The rule of merging is: if two nodes overlap, then add the values ​​of these two nodes as the new value of the merged node; otherwise, the node that is not null will be directly used as the node of the new binary tree.
Returns the merged binary tree.

Note: The merging process must start from the root node of both trees.
insert image description here

3.1 Recursion/Depth First

I really didn't think about how to do it at first. The main idea is to create a new binary tree, and then add the corresponding subtrees recursively, which is the subtree of the new binary tree, and then just return.

public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
    
    
        if(root1==null) return root2;
        if(root2==null) return root1;
        // 先记录下当前两个节点的之和
        TreeNode merged = new TreeNode(root1.val+root2.val);
        // 新子树的左节点通过递归获取
        merged.left=mergeTrees(root1.left,root2.left);
        merged.right=mergeTrees(root1.right,root2.right);
        return merged;
    }

insert image description here

3.2 Iteration/Breadth

It is still building a tree, but it needs to use three queues to store the nodes of the corresponding tree, and then add the values ​​of the left subtree and the right subtree of the two numbers respectively, and the left and right subtrees of the new binary tree come out.

public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
    
    
        if(root1 == null) return root2;
        if(root2 == null) return root1;
        TreeNode merged = new TreeNode(root1.val+root2.val);
        // 存储新二叉树
        Queue<TreeNode> queue = new LinkedList<>();
        // 存储root1
        Queue<TreeNode> queue1 = new LinkedList<>();
        // 存储root2
        Queue<TreeNode> queue2 = new LinkedList<>();
        queue.offer(merged);
        queue1.offer(root1);
        queue2.offer(root2);
        while(!queue.isEmpty() && !queue1.isEmpty() && !queue2.isEmpty()){
    
    
            TreeNode node = queue.remove();
            TreeNode node1 = queue1.remove();
            TreeNode node2 = queue2.remove();
            TreeNode left1 = node1.left,right1=node1.right;
            TreeNode left2 = node2.left,right2=node2.right;
            // 左节点合并
            if(left1!= null || left2!=null){
    
    
                if(left1!=null && left2!=null){
    
    
                    TreeNode left = new TreeNode(left1.val+left2.val);
                    node.left = left;
                    queue.offer(left);
                    queue1.offer(left1);
                    queue2.offer(left2);
                }else if(left1!=null){
    
    
                    node.left = left1;
                }else{
    
    
                    node.left = left2;
                }
            }

            // 右节点合并
            if(right1!=null || right2!=null){
    
    
                if(right1!=null && right2!=null){
    
    
                    TreeNode right = new TreeNode(right1.val+right2.val);
                    node.right = right;
                    queue.offer(right);
                    queue1.offer(right1);
                    queue2.offer(right2);
                }else if(right1!=null){
    
    
                    node.right = right1;
                }else{
    
    
                    node.right = right2;
                }
            }
        }

        return merged;
    }

insert image description here

Disadvantages: Three queues are used to store the values ​​of three binary trees respectively, which is a waste of space and requires a lot of code.
Time complexity: O(min(m,n)) where m and n represent the number of nodes in the two binary trees Space
complexity: O(min(m,n)) depends on the number of elements in the queue.

Summarize

The above methods all use recursion, that is, deep traversal, with less code and clear and easy to understand, while iterative and breadth traversal use more code, and need to use the corresponding queue to store elements every time.

Guess you like

Origin blog.csdn.net/qq_52843958/article/details/132083760