典型的な演習の概要バイナリツリー

バイナリツリートラバーサル三つの方法: 

1.はそれを返すための先行順走査でバイナリツリーを考えます。ルートは左から右

再帰:

    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;
      
    }

非再帰的な実装: 

アイデアは分析:[]スタックの実装に行き、左、毎回、CUR印刷とスタックが空ではありません。スタックの先頭を取得する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.それを返すために、行きがけにバイナリツリーを考えます。左ルート右

再帰:

    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;
    }

非再帰:ちょうど別の場所を追加し、先行順走査。 

  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.バイナリツリーを考えると、それは後順トラバーサルを返します。左右ルート

再帰:

    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;
    }

非再帰:[]スタックの実装

    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.必要なノードの数

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

求めているリーフノードの数

      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. kレベルのノードシークの数

分析思考:現在のレベルkのルートを見つけ、K-1は、現在のレイヤーノードroot.rightの現在root.left + K-1層の数に相当します

   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);
    }

左 - - 右ヴァル、見つからないか、nullのルートノードのための7ルック

    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;
    }

同じ2つのツリーかどうかをチェックします8.

   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.サブツリーの別の木

    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;
    }

前記バイナリツリーの最大深さ

アイデア分析:最大深さは、ツリーの高さで最大レベルノード、です。すなわち、+1の値が大きいほど、ツリーの左側のツリーの右高さの高さ(ルート)であります

      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は、平衡二分木であるか否かを判定する
高さのバランスの取れた二分木が定義されているバイナリツリーの各ノード ではない以上1未満の左と右のサブツリーの高さの差の絶対値。

思考の分析:まず、我々は、その後、root.leftとroot.rightがバランスされていないと判断された場合、ルートノードは、バランスされていないかを決定しなければなりません。

 

    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;
    }

前記二値画像

アイデアの分析:

まず、このようなマップは、我々は、ミラーが二分木は、2つの必要条件を有していること①②デジタルの対称の位置に対応する等しくなければならないでしょう。もちろん機能は、問題を解決していません。したがって、現在のルートは、現在のルートが空であるかどうかを判断し、ルートノードです。ルート左側のツリーの値は右ツリー&& leftTree.leftの値に等しいときに、rightTree.rightは、ミラーリングされたバイナリ&& leftTree.rightバイナリツリーの確立は、バイナリツリーミラーであるが、三つの条件は、ミラーをrightTree.leftあります。

図II図III図IV:2つの特殊なケースがあることに注意してください。

       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.バイナリツリートラバーサル配列

    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

おすすめ

転載: blog.csdn.net/qq_41185460/article/details/103568655
おすすめ