Typical exercises summary binary tree

Binary tree traversal three ways: 

1. Given a binary tree in preorder traversal to return it. root-left-right

Recursive:

    public List<Integer> preorderTraversal(TreeNode root) {
       List<Integer> list = new ArrayList<>();  //每次遍历都会产生一个新的list对象
       if(root == null) {
           return list;
       } 
       System.out.print(root.val + " ");
       list.add(root.val);
       List<Integer> list1 = preorderTraversal(root.left);
       list.addAll(list1);
       List<Integer> list2 =  preorderTraversal(root.right);
       list.addAll(list2);
       return list;
      
    }

Non-recursive implementation: 

Ideas Analysis: [] stack implementation left to go, every time, cur print and stack is not empty; to get the top of the stack is empty, cur = cur.right.

    void preOrderTraversalNor(TreeNode root) {
        Stack<TreeNode > stack = new Stack<>();
        TreeNode cur = root;
        while (cur != null || !stack.empty()) {
            while (cur != null) {
                stack.push(cur);
                System.out.print(cur.value + " ");
                cur = cur.left;
            }
            cur = stack.pop();
            cur = cur.right;
        }
    }
    List<Character> preOrderTraversalNor2(TreeNode root) {
       List<Character> list = new ArrayList<>();
        Stack<TreeNode > stack = new Stack<>();
        TreeNode cur = root;
        while (cur != null || !stack.empty()) {
            while (cur != null) {
                stack.push(cur);
                System.out.print(cur.value + " ");
                list.add(cur.value);
                cur = cur.left;
            }
            cur = stack.pop();
            cur = cur.right;
        }
        return list;
    }

2. Given a binary tree in preorder to return it. left-root-right

Recursive:

    public List<Integer> inorderTraversal(TreeNode root) {
       List<Integer> list = new ArrayList<>();
       if(root == null) {
           return list;
       } 
       List<Integer> list1 = inorderTraversal(root.left);
       list.addAll(list1);

       System.out.print(root.val + " ");
       list.add(root.val);

       List<Integer> list2 =  inorderTraversal(root.right);
       list.addAll(list2);
       return list;
    }

Non-recursive: just add and preorder traversal different locations. 

  List<Character> preOrderTraversalNor2(TreeNode root) {
       List<Character> list = new ArrayList<>();
        Stack<TreeNode > stack = new Stack<>();
        TreeNode cur = root;
        while (cur != null || !stack.empty()) {
            while (cur != null) {
               stack.push(cur);
               cur = cur.left;
            }
            cur = stack.pop();
            list.add(cur.value);
            cur = cur.right;
        }
        return list;
    }

3. Given a binary tree, it returns postorder traversal. left-right-root

Recursive:

    public List<Integer> postorderTraversal(TreeNode root) {
       List<Integer> list = new ArrayList<>();
       if(root == null) {
           return list;
       } 
       List<Integer> list1 = postorderTraversal(root.left);
       list.addAll(list1);

       List<Integer> list2 =  postorderTraversal(root.right);
       list.addAll(list2);

       System.out.print(root.val + " ");
       list.add(root.val);

       return list;
    }

Non-recursive: [] stack implementation

    void postOrderTraversalnNor(TreeNode root) {
        Stack<TreeNode > stack = new Stack<>();
        TreeNode cur = root;
        TreeNode prev = null;
        while (cur != null || !stack.empty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            //cur = null;  ??
            cur = stack.peek();
            if(cur.right == null || cur.right == prev) {
                stack.pop();
                System.out.print(cur.value+" ");
                prev = cur;
                cur = null;
            }else {
                cur = cur.right;
            }
        }

    }
   public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        Stack<TreeNode > stack = new Stack<>();
        TreeNode cur = root;
        TreeNode prev = null;
        while (cur != null || !stack.empty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            //cur = null;  异议
            cur = stack.peek();
            if(cur.right == null || cur.right == prev) {
                stack.pop();
                System.out.print(cur.val+" ");
                list.add(cur.val);
                prev = cur;
                cur = null;
            }else {
                cur = cur.right;
            }
        }
        return list;
    }

 

4. The number of nodes required

  //左子树的节点个数+右子树的节点的个数+1
  public int getSize(TreeNode root) {
        if (root == null) {
            return 0;
        }
        return getSize(root.left) + getSize(root.right) +1;
    }

The number of leaf nodes seeking

      public int getLeafSize(TreeNode root) {
        if (root == null) {
            return 0;
        } else if (root.left == null && root.right == null) {
            return 1;
        }
        return getLeafSize(root.left) + getLeafSize(root.right);
    }

6. The number of k-level node seeking

Thinking Analysis: find the root of the current level k, k-1 is equivalent to the number of the current root.left + k-1 layer of the current layer node root.right

   int getKLevelSize(TreeNode root, int k) {
        if (root == null) {
            return 0;
        }
        if (k == 1) {
            return 1;
        }
        return getKLevelSize(root.left, k-1) + getKLevelSize(root.right, k-1);
    }

7. Look for the node where val, not found or null root - left - right

    TreeNode find(TreeNode root, int val) {
        if (root == null) {
            return null;
        }
        if (root.value == val) {
            return root;
        }
        TreeNode ret = find(root.left, val);
        if (ret != null) {
            return ret;
        }
        ret = find(root.right, val);
        if (ret != null) {
            return ret;
        }
        return null;
    }

8. Check whether the same two trees

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

9. Another tree of subtrees

    public boolean isSubtree(TreeNode s, TreeNode t) {
        if (s == null || t == null) return false;
        if(isSameTree(s,t))  return true;
        if (isSameTree(s.left,t)) return true;
        if (isSameTree(s.right,t)) return true;
        return false;
    }

10. The maximum depth of the binary tree

Ideas Analysis: The maximum depth is the greatest level node, which is the height of the tree. That is, the height of the larger value of +1 and the right height of the tree left of the tree (root)

      public int maxDepth(TreeNode root) {
        if(root == null) {
            return 0;
        }
        int leftHight = maxDepth(root.left);
        int rightHight = maxDepth(root.right);

        return leftHight > rightHight
                ? leftHight + 1 : rightHight + 1;
    }

11 determines whether a balanced binary tree is a
balanced binary tree of height is defined: a binary tree each node of  the absolute value of the difference between the height of the left and right subtrees of not more than 1.

Analysis of thinking: First, we must determine the root node is not balanced, if it is then judged root.left and root.right is not balanced.

 

    public boolean isBalanced(TreeNode root) {
        if(root == null) {
            return true;
        }
        int leftHight = maxDepth(root.left);
        int rightHight = maxDepth(root.right);

        return Math.abs(leftHight-rightHight) <= 1
        && isBalanced(root.left)
        && isBalanced(root.right);
    }


     public int maxDepth(TreeNode root) {
        if(root == null) {
            return 0;
        }
        int leftHight = maxDepth(root.left);
        int rightHight = maxDepth(root.right);

        return leftHight > rightHight
                ? leftHight + 1 : rightHight + 1;
    }

12. The binary image

Analysis of ideas:

First, such a map, we will find that mirrors the binary tree has two necessary conditions ① ② corresponding to the symmetrical position of the digital must be equal. Obviously a function does not solve the problem. Thus, the current root is the root node, it is determined whether the current root is empty. Then when the value of root left tree is equal to the value of the right tree && leftTree.left, rightTree.right is mirrored binary && leftTree.right, three conditions rightTree.left mirror while the establishment of the binary tree is a binary tree mirror.

Note that there are two special cases: Figure II Figure III Figure IV.

       public boolean isSymmetricChild(TreeNode leftTree,TreeNode rightTree) {
        if(leftTree == null && rightTree!= null ||  leftTree != null && rightTree == null) {
            return false;
        }
        if(leftTree == null && rightTree == null) {
            return true;
        }
        return leftTree.val == rightTree.val &&
        isSymmetricChild(leftTree.left,rightTree.right)
        &&isSymmetricChild(leftTree.right,rightTree.left);
    }
    public boolean isSymmetric(TreeNode root) {
        if(root == null) {
            return true;
        }
        return isSymmetricChild(root.left,root.right);
    }

13. The binary tree traversal sequence

    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ret = new ArrayList<>();

        Queue<TreeNode> queue = new LinkedList<>();
        if(root != null) {
            queue.offer(root);
        }
        while (!queue.isEmpty()) {
            int size = queue.size();//1
            List<Integer> list = new ArrayList<>();
            while (size > 0) {
                TreeNode cur = queue.poll();
                System.out.print(cur.val+" ");
                list.add(cur.val);
                size--;//0
                if(cur.left != null) {
                    queue.offer(cur.left);
                }
                if(cur.right != null) {
                    queue.offer(cur.right);
                }
            }
            ret.add(list);
        }
        return ret;
    }

14.判断一棵树是不是完全二叉树

思路分析:需要构造一个队列。当cur不为空时让cur入队列。当队列不为空时,让cur的左右节点入队列;当队列元素全为null时,说明这个树是完全二叉树;否则不是。

注意:如果是完全二叉树,遇到null 说明所有元素都放入队列 ;如果不是完全二叉树,那就不一定啦。

    boolean isCompleteTree(TreeNode root){
        Queue<TreeNode> queue = new LinkedList<>();
        if(root != null) {
            queue.offer(root);
        }
        while (!queue.isEmpty()) {
            TreeNode cur = queue.poll();
            if(cur != null) {
                queue.offer(cur.left);
                queue.offer(cur.right);
            }else {
                break;
            }
        }

        while (!queue.isEmpty()) {
            TreeNode cur = queue.peek();
            if(cur != null) {
                return false;
            }else {
                queue.poll();
            }
        }
        return true;
    }

15.二叉树的构建及遍历

    public static int i = 0;
    public static TreeNode buildTree(String str) {
        TreeNode root = null;
        if(str.charAt(i) != '#') {
            root = new TreeNode(str.charAt(i));
            i++;
            root.left = buildTree(str);
            root.right = buildTree(str);
        }else {
            i++;
        }
        return root;
    }
//前序遍历的方式进行思考
class Solution {

    int preIndex = 0;

     public TreeNode buildTreeChild(int[] preorder,
    int[] inorder,int inbegin,int inend) {
         //判断是否有左树或者是右树
         if(inbegin > inend) {
             return null;
         }
         TreeNode root = new TreeNode(preorder[preIndex]);
         //找root在中序遍历的下标
         int rootIndex =
         findIndexOfInorder(inorder,inbegin,inend,preorder[preIndex]);
        preIndex++;

        root.left = buildTreeChild(preorder ,inorder,inbegin,
        rootIndex-1);

        root.right = buildTreeChild(preorder ,inorder
        ,rootIndex+1,inend);

        return root;
     }

     public int findIndexOfInorder(int[] inorder,int inbegin,
     int inend,int val){
         for(int i = inbegin;i <= inend;i++) {
             if(inorder[i] == val) {
                 return i;
             }
         }
         return -1;
     }


    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder == null || inorder == null) {
            return null;
        }
        if(preorder.length == 0 || inorder.length ==0) {
            return null;
        }

       return buildTreeChild(preorder,inorder,0,inorder.length-1);
    }
}

 

16.给定一个二叉树,找到该树中两个指定节点的最近公共祖先

    public TreeNode find (TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) {
            return null;
        }
        if (root == p || root == q) {
            return root;
        }
        TreeNode leftTree = find(root.left, p, q);
        TreeNode rightTree = find(root.right, p, q);
        if (leftTree != null && rightTree != null) {
            return root;
        }
        if (leftTree != null) {
            return leftTree;
        }
        if (rightTree != null) {
            return rightTree;
        }
        return null;
    }

17.二叉搜索树转化为排序双向链表

    TreeNode prev = null; //标记上一个节点
    public void ConvertChild(TreeNode pCur) {
        if(pCur == null) {
            return;
        }
        ConvertChild(pCur.left);
        pCur.left = prev;
        if(prev != null) {
            prev.right = pCur;
        }
        prev = pCur;
        ConvertChild(pCur.right);
    }

    //返回的是双向链表的头结点
    public TreeNode Convert(TreeNode pRootOfTree) {
        //这个函数,执行完成后,二叉搜索树的结构已经被改变了
        ConvertChild(pRootOfTree);
        TreeNode head = pRootOfTree;
        //一路向左
        while (head != null && head.left != null) {
            head = head.left;
        }
        return head;
    }

 

18.根据一棵树的前序遍历和中序遍历构建二叉树

class Solution {

    int preIndex = 0;

     public TreeNode buildTreeChild(int[] preorder,
    int[] inorder,int inbegin,int inend) {
         //判断是否有左树或者是右树
         if(inbegin > inend) {
             return null;
         }
         TreeNode root = new TreeNode(preorder[preIndex]);
         //找root在中序遍历的下标
         int rootIndex =
         findIndexOfInorder(inorder,inbegin,inend,preorder[preIndex]);
        preIndex++;

        root.left = buildTreeChild(preorder ,inorder,inbegin,
        rootIndex-1);

        root.right = buildTreeChild(preorder ,inorder
        ,rootIndex+1,inend);

        return root;
     }

     public int findIndexOfInorder(int[] inorder,int inbegin,
     int inend,int val){
         for(int i = inbegin;i <= inend;i++) {
             if(inorder[i] == val) {
                 return i;
             }
         }
         return -1;
     }


    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if(preorder == null || inorder == null) {
            return null;
        }
        if(preorder.length == 0 || inorder.length ==0) {
            return null;
        }

       return buildTreeChild(preorder,inorder,0,inorder.length-1);
    }
}

19..根据一棵树的中序遍历和后序遍历构建二叉树

class Solution {
    public int postIndex = 0;

    public TreeNode buildTreeChild(int[] inorder,
     int[] postorder,int inbegin,int inend) {
         //判断是否有左树或者是右树
         if(inbegin > inend) {
             return null;
         }
         TreeNode root = new TreeNode(postorder[postIndex]);
         //找root在中序遍历的下标
         int rootIndex =
         findIndexOfInorder(inorder,inbegin,inend,postorder[postIndex]);
        postIndex--;

          root.right = buildTreeChild(inorder
        ,postorder ,rootIndex+1,inend);


        root.left = buildTreeChild(inorder ,postorder,inbegin,
        rootIndex-1);


        return root;
     }

     public int findIndexOfInorder(int[] inorder,int inbegin,
     int inend,int val){
         for(int i = inbegin;i <= inend;i++) {
             if(inorder[i] == val) {
                 return i;
             }
         }
         return -1;
     }

    public TreeNode buildTree(int[] inorder, int[] postorder) {
     if(postorder == null || inorder == null) {
            return null;
        }
        if(postorder.length == 0 || inorder.length ==0) {
            return null;
        }
       postIndex = postorder.length-1;
       return buildTreeChild(inorder,postorder,0,inorder.length-1);
    }
}

20.二叉树创建字符串

 

class Solution {

    public void tree2strChild(TreeNode t,StringBuilder sb) {
        if(t == null) {
            return ;
        }
        sb.append(t.val);
        if(t.left == null) {
            if(t.right == null) {
                return;
            }else{
                sb.append("()");
            }
        }else{
            sb.append("(");
            tree2strChild(t.left,sb);
            sb.append(")");
        }
        //以上代码是递归前t的位置
        if(t.right == null) {
            return;
        }else{
            sb.append("(");
            tree2strChild(t.right,sb);
            sb.append(")");
        }

    }

    public String tree2str(TreeNode t) {
        StringBuilder sb = new StringBuilder();

        tree2strChild(t,sb);

        return sb.toString();
    }
}

 

发布了51 篇原创文章 · 获赞 14 · 访问量 2306

Guess you like

Origin blog.csdn.net/qq_41185460/article/details/103568655