剑指offer:二叉树、二叉树搜索树

package BST;

import java.util.*;

public class BST {

    /*
     * 重建二叉树
     * 先找到root,再递归构建root的左子树root.left和右子树root.right
     * */
    public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
        if (pre == null || in == null) {
            return null;
        }
        if (pre.length == 0 || in.length == 0) {
            return null;
        }

        TreeNode root = new TreeNode(pre[0]);

        for (int i = 0; i < in.length; i++) {
            if (in[i] == pre[0]) {
                root.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(in, 0, i));
                root.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i + 1, pre.length), Arrays.copyOfRange(in, i + 1, in.length));
            }
        }
        return root;
    }


    /*
     * 判断给定数组是否是二分搜索树的后续遍历
     * 1.如果数组为空/长度为零,返回false
     * 2.二分搜索树的根不断变化,递归调用,需要start,end参数指定二分搜索树的根节点
     * 3.私有函数:判断从start到end范围的数组是否为后续遍历,判断方法是找到第一个大于根节点的节点,
     * 再判断右子树的节点值是否都大于根节点,如果不是,返回false
     * 4.递归调用确定左右子树的根节点所在范围
     *
     * */
    public boolean VerifySquenceOfBST(int[] sequence) {
        if (sequence == null || sequence.length == 0) {
            return false;
        }

        return VerifySquenceOfBST(sequence, 0, sequence.length - 1);
    }

    private boolean VerifySquenceOfBST(int[] sequence, int start, int end) {
        if (start >= end) {
            return true;
        }
        int i = start;
        while (sequence[i] < sequence[end]) {
            i++;
        }
        for (int j = i; j < end; j++) {
            if (sequence[j] < sequence[end]) {
                return false;
            }
        }

        return VerifySquenceOfBST(sequence, start, i - 1) && VerifySquenceOfBST(sequence, i, end - 1);
    }


    /*
     * 判断给定数组是否是二分搜索树的后续遍历 (没有用私有函数的写法)
     * 1.如果数组为空/长度为零,返回false
     * 2.二分搜索树的根不断变化,递归调用,需要start,end参数指定二分搜索树的根节点
     * 3.私有函数:判断从start到end范围的数组是否为后续遍历,判断方法是找到第一个大于根节点的节点,
     * 再判断右子树的节点值是否都大于根节点,如果不是,返回false
     * 4.递归调用确定左右子树的根节点所在范围
     *
     * */
    public boolean VerifySquenceOfBST1(int[] sequence) {

        int len = sequence.length;
        if (len == 0) return false;
        int root = sequence[len - 1];
        int i = 0;
        for (; i < len - 1; i++) {
            if (sequence[i] > root) break;
        }
        int j = i;
        for (; j < len - 1; j++) {
            if (sequence[j] < root) return false;
        }
        boolean left = true, right = true;
        if (i > 0) left = VerifySquenceOfBST1(Arrays.copyOfRange(sequence, 0, i));
        if (i < len - 1) right = VerifySquenceOfBST1(Arrays.copyOfRange(sequence, i, len - 1));
        return left && right;
    }


   /*
    *二叉树的下一个节点
    * 若果X有右孩子,下一个节点是右孩子最左边节点
    * 如果X没有右孩子,找到X的parent,若p的左孩子是X,下一个节点就是p,否则p往上找(p = p.p,x = p)
    * */
    public class Node{
        private int val;
        private Node left;
        private Node right;
        private Node parent;
    }

    public  Node getSuccessorNode(Node node) {
        if (node == null) {
            return null;
        }
        if (node.right != null) {
            return getLeftMost(node.right);
        } else {
            Node parent = node.parent;
            while (parent != null && parent.left != node) {
                node = parent;
                parent = node.parent;
            }
            return parent;
        }
    }

    public  Node getLeftMost(Node node) {
        if (node == null) {
            return node;
        }
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }

    /*
    * 二叉树层序遍历
    * */
    public void levelOrder(TreeNode head){
        ArrayList<ArrayList<TreeNode>> results=new ArrayList<>();
        ArrayList<TreeNode> levelList = new ArrayList<>();
        TreeNode last = head;//初始化当前层最后节点
        TreeNode nlast = null;//记录下次要更换的最后节点
        Queue<TreeNode> q = new LinkedList<>();
        q.add(head);
        while(!q.isEmpty()){
            TreeNode cur = q.remove();
            //System.out.println(cur.value);
            levelList.add(cur);

            if(cur.left != null) {
                q.add(cur.left);
                nlast = cur.left;
            }

            if(cur.right != null) {
                q.add(cur.right);
                nlast = cur.right;
            }

            if (cur == last) {//当前访问节点为该层的最后一个节点
                results.add(levelList);
                levelList = new ArrayList<TreeNode>();
                last = nlast;
            }

        }
    }

    /*
     * 树的子结构
     *判断root2是否是root1的子树
     *分为两步:第一步遍历root1这棵树,寻找和root2根节点相同的结点
     * */

    public boolean HasSubtree(TreeNode root1, TreeNode root2) {


        boolean res = false;
        if (root1 != null && root2 != null) {
            if (root1.val == root2.val) {
                res = tree1HasTree2(root1, root2);
            }
            if (!res) {
                res = HasSubtree(root1.left, root2);
            }
            if (!res) {
                res = HasSubtree(root1.right, root2);
            }
        }
        return res;
    }

    //root1.val = root2.val的情况下,判断其左右子树的值是否相同
    private boolean tree1HasTree2(TreeNode root1, TreeNode root2) {

        if (root1 == null && root2 != null) {
            return false;
        }

        if (root2 == null) {
            return true;
        }

        if (root1.val != root2.val) {
            return false;
        }
        return tree1HasTree2(root1.left, root2.left) && tree1HasTree2(root1.right, root2.right);
    }

    /*
     * 二叉树的镜像
     *
     * */
    public void Mirror(TreeNode root) {
        if (root == null) {
            return;
        }

        if (root.left != null || root.right != null) {
            TreeNode temp = root.left;
            root.left = root.right;
            root.right = temp;
            Mirror(root.left);
            Mirror(root.right);
        }
    }

    /*
     * 二叉搜索树的中序非递归遍历
     * 当前节点不为空,入栈,一直往左窜;当前节点不为空访问该节点,往右
     * */
    public void inOrder(TreeNode head) {
        if (head != null) {
            Stack<TreeNode> stack = new Stack<>();
            while (head != null || !stack.isEmpty()) {
                if (head != null) {
                    stack.push(head);
                    head = head.left;
                } else {
                    head = stack.pop();
                    System.out.println(head.val);//
                    head = head.right;
                }
            }
        }
    }
    /*
     * 二叉搜索树与双向链表
     * 当前节点不为空,入栈,一直往左窜;当前节点不为空出栈访问该节点,往右
     * */
    public TreeNode Convert(TreeNode root) {
        if (root == null) {
            return null;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode pre = null;
        TreeNode cur = root;
        boolean flag = true;
        while (cur != null || !stack.isEmpty()) {
            if (cur!=null){
                stack.push(cur);
                cur = cur.left;
            }else {
                cur = stack.pop();
                if (flag){//第一次,cur为root
                    root = cur;
                    pre = root;
                    flag = false;
                }else {
                    pre.right = cur;
                    cur.left = pre;
                    pre = cur;
                }
                cur = cur.right;

            }
        }
        return root;
    }

    /*判断是否为对称二叉树
    * 对称的树的左子树和右子树满足以下条件:都为空,一个空,都不空
    * 1.如果左子树或右子树均为空,则该树对称;
    * 2.如果左子树或右子树只有一个为空,则该树不对称;
    * 3.如果左子树和右子树均不为空,当左子树的左子树和右子树的右子树镜像对称,
    * 且左子树的右子树和右子树的左子树   镜像对称时,该树对称。
    * */

    /*
    判断两颗树是否相同
        两棵二叉树均为空,则相等;
        两棵二叉树其中一棵为空,另一棵不为空,则不相等;
        两棵二叉树均不为空,如果根节点的值相等,左子树相等和右子树相等,则这两棵二叉树相等,否则不相等。
    */

    boolean isSymmetrical(TreeNode pRoot) {

        if (pRoot == null) {
            return true;
        }
        return isCommon(pRoot.left, pRoot.right);
    }

    public boolean isCommon(TreeNode left, TreeNode right) {
        if (left == null && right == null) {
            return true;
        }
        if (left != null && right != null) {
            return left.val == right.val && isCommon(left.left,right.right )&&isCommon(left.right,right.left );
        }
        return false;
    }


    /*
    * 二叉搜索树第k个节点
    * */
    int count = 0;
    TreeNode KthNode(TreeNode pRoot, int k) {
        if (pRoot != null) {
            TreeNode left = KthNode(pRoot.left, k);
            if (left != null) {
                return left;
            }
            count++;
            if (count==k){
                return pRoot;
            }
            TreeNode right = KthNode(pRoot.right,k );
            if (right!=null){
                return right;
            }

        }
        return null;
    }


    /*
     * 二叉搜索树第k个节点(方法二)
     * */
    ArrayList<TreeNode> list = new ArrayList<>(); // (1)
    TreeNode KthNode1(TreeNode pRoot, int k)
    {
        addNode(pRoot);

        if(k>=1 && list.size()>=k) {
            return list.get(k-1);
        }

        return null;

    }
    // 中序遍历
    void addNode(TreeNode cur) {   // (2)
        if(cur != null) {
            addNode(cur.left);
            list.add(cur);
            addNode(cur.right);
        }
    }

}

/*
    * 序列化和反序列化
    * */
    String Serialize(TreeNode root) {
        if (root == null) {
            return "#!";
        }
        String s = root.val + "!";

        s = s + Serialize(root.left);
        s = s + Serialize(root.right);
        return s;

    }

    TreeNode Deserialize(String str) {
        String[] values = str.split("!");
        Queue<String> queue = new LinkedList<>();
        for (int i = 0;i<values.length;i++){
            queue.offer(values[i]);
        }

        return reConpre(queue);
    }

    private TreeNode reConpre(Queue<String> queue) {
        String value = queue.poll();
        if (value.equals("#")){
            return null;
        }
        TreeNode head = new TreeNode(Integer.valueOf(value));
        head.left = reConpre(queue);
        head.right = reConpre(queue);
        return head;
    }

猜你喜欢

转载自www.cnblogs.com/susanhe/p/11919033.html