面试常见算法2:对树的操作

1、树的遍历:先序/中序/后序/层次遍历

package sword_to_offer_tree;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class PreInPosLayerTraversal {
    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int value) {
            this.value = value;
        }
    }

    public static void preOrderRecur(Node head) {
        if (head == null) return;
        System.out.print(head.value + " ");
        preOrderRecur(head.left);
        preOrderRecur(head.right);
    }

    public static void inOrderRecur(Node head) {
        if (head == null) return;
        inOrderRecur(head.left);
        System.out.print(head.value + " ");
        inOrderRecur(head.right);
    }

    public static void posOrderRecur(Node head) {
        if (head == null) return;
        posOrderRecur(head.left);
        posOrderRecur(head.right);
        System.out.print(head.value + " ");
    }

    // 用栈实现,弹出当前节点,有右先压右,有左后压左
    // 先压右后压左,弹出为先弹左后弹右
    public static void preOrderUnRecur(Node head) {
        if (head == null) return;
        Stack<Node> stack = new Stack<>();
        stack.push(head);
        while (!stack.isEmpty()) {
            head = stack.pop();
            System.out.print(head.value + " ");
            // 有右先压右
            if (head.right != null) {
                stack.push(head.right);
            }
            // 有左后压左
            if (head.left != null) {
                stack.push(head.left);
            }
        }
        System.out.println();
    }

    // 用栈实现,当前节点不为空或者栈不为空继续:当前节点不为空,当前节点压入栈,当前节点往左跑(左边界一压压一溜);当前节点为空,从栈中拿一个打印,当前节点向右跑
    public static void inOrderUnRecur(Node head) {
        if (head == null) return;
        Stack<Node> stack = new Stack<>();
        while (head != null || !stack.isEmpty()) {
            if (head != null) {
                stack.push(head);
                head = head.left;
            } else {
                head = stack.pop();
                System.out.print(head.value + " ");
                head = head.right;
            }
        }
        System.out.println();
    }

    // 后序:左-右-中
    // 通过 中-左-右(先序) -> 中-右-左,打印的时候不打印,存到栈里去,存完把所有栈中的元素打印 -> 左-右-中
    public static void posOrderUnRecur(Node head) {
        if (head == null) return;
        Stack<Node> stack = new Stack<>();
        Stack<Integer> printStack = new Stack<>();
        stack.push(head);
        while (!stack.isEmpty()) {
            head = stack.pop();
            // System.out.print(head.value + " ");
            printStack.push(head.value);
            // 有左先压左
            if (head.left != null) {
                stack.push(head.left);
            }
            // 有右后压右
            if (head.right != null) {
                stack.push(head.right);
            }
        }
        while (!printStack.isEmpty()) {
            System.out.print(printStack.pop() + " ");
        }
        System.out.println();
    }

    // 弹一个出来,把左边右边加进去
    public static void layerTraversal(Node head) {
        if (head == null) return;
        Queue<Node> queue = new LinkedList<>();
        queue.offer(head);
        while (!queue.isEmpty()) {
            head = queue.poll();
            System.out.print(head.value + " ");
            if (head.left != null) {
                queue.offer(head.left);
            }
            if (head.right != null) {
                queue.offer(head.right);
            }
        }
    }

    // for LinkedListHasLoopOrNot -- print tree
    public static void printTree(Node head) {
        System.out.println("Binary Tree:");
        printInOrder(head, 0, "H", 17);
        System.out.println();
    }

    public static void printInOrder(Node head, int height, String to, int len) {
        if (head == null) {
            return;
        }
        printInOrder(head.right, height + 1, "v", len);
        String val = to + head.value + to;
        int lenM = val.length();
        int lenL = (len - lenM) / 2;
        int lenR = len - lenM - lenL;
        val = getSpace(lenL) + val + getSpace(lenR);
        System.out.println(getSpace(height * len) + val);
        printInOrder(head.left, height + 1, "^", len);
    }

    public static String getSpace(int num) {
        String space = " ";
        StringBuffer buf = new StringBuffer("");
        for (int i = 0; i < num; i++) {
            buf.append(space);
        }
        return buf.toString();
    }


    public static void main(String[] args) {
        Node head = new Node(5);
        head.left = new Node(3);
        head.right = new Node(8);
        head.left.left = new Node(2);
        head.left.right = new Node(4);
        head.left.left.left = new Node(1);
        head.right.left = new Node(7);
        head.right.left.left = new Node(6);
        head.right.right = new Node(10);
        head.right.right.left = new Node(9);
        head.right.right.right = new Node(11);
        printTree(head);

        // recursive
        System.out.println("==============recursive==============");
        System.out.print("pre-order: ");
        preOrderRecur(head);
        System.out.println();
        System.out.print("in-order: ");
        inOrderRecur(head);
        System.out.println();
        System.out.print("pos-order: ");
        posOrderRecur(head);
        System.out.println();

        // unrecursive
        System.out.println("============unrecursive=============");
        System.out.print("pre-order: ");
        preOrderUnRecur(head);
        System.out.print("in-order: ");
        inOrderUnRecur(head);
        System.out.print("pos-order: ");
        posOrderUnRecur(head);

        // layer
        System.out.println("============layer=============");
        layerTraversal(head);
    }
}

2、找树中某个节点的前驱/后继节点

2.1 找后继节点

package sword_to_offer_tree;

// 后继节点,即中序遍历中的下一个节点
public class FindSuccessorNode {
    public static class Node {
        public int value;
        public Node left;
        public Node right;
        public Node parent;

        public Node(int data) {
            this.value = data;
        }
    }

    // 若有右子树,则为右子树上最左的节点;若没有右子树,则为第一个满足某种要求的父节点,要求是我在该父节点的左子树上
    public static Node findSuccessorNode(Node head) {
        if (head == null) return null;
        if (head.right != null) return findLeftMostNode(head.right);
        else return findFatherWhichIamInHisLeft(head);
    }

    public static Node findLeftMostNode(Node node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }

    public static Node findFatherWhichIamInHisLeft(Node node) {
        Node parent = node.parent;
        while (parent != null) {
            if (parent.left == node) {
                return parent;
            } else {
                node = parent;
                parent = parent.parent;
            }
        }
        return parent;
    }
    public static void main(String[] args) {
        Node head = new Node(6);
        head.parent = null;
        head.left = new Node(3);
        head.left.parent = head;
        head.left.left = new Node(1);
        head.left.left.parent = head.left;
        head.left.left.right = new Node(2);
        head.left.left.right.parent = head.left.left;
        head.left.right = new Node(4);
        head.left.right.parent = head.left;
        head.left.right.right = new Node(5);
        head.left.right.right.parent = head.left.right;
        head.right = new Node(9);
        head.right.parent = head;
        head.right.left = new Node(8);
        head.right.left.parent = head.right;
        head.right.left.left = new Node(7);
        head.right.left.left.parent = head.right.left;
        head.right.right = new Node(10);
        head.right.right.parent = head.right;

        Node test = head.left.left;
        System.out.println(test.value + " next: " + findSuccessorNode(test).value);
        test = head.left.left.right;
        System.out.println(test.value + " next: " + findSuccessorNode(test).value);
        test = head.left;
        System.out.println(test.value + " next: " + findSuccessorNode(test).value);
        test = head.left.right;
        System.out.println(test.value + " next: " + findSuccessorNode(test).value);
        test = head.left.right.right;
        System.out.println(test.value + " next: " + findSuccessorNode(test).value);
        test = head;
        System.out.println(test.value + " next: " + findSuccessorNode(test).value);
        test = head.right.left.left;
        System.out.println(test.value + " next: " + findSuccessorNode(test).value);
        test = head.right.left;
        System.out.println(test.value + " next: " + findSuccessorNode(test).value);
        test = head.right;
        System.out.println(test.value + " next: " + findSuccessorNode(test).value);
        test = head.right.right; // 10's next is null
        System.out.println(test.value + " next: " + findSuccessorNode(test));
    }
}

2.2 找前驱节点

package sword_to_offer_tree;

public class FindPrecursorNode {
    public static class Node {
        public int value;
        public Node left;
        public Node right;
        public Node parent;

        public Node(int value) {
            this.value = value;
        }
    }

    // 若有左子树,则为左子树上最右的节点;若没有左子树,则为第一个满足某种要求的父节点,要求是我在该父节点的右子树上
    public static Node findPrecursorNode(Node head) {
        if (head == null) return head;
        if (head.left != null) return findRightMost(head.left);
        else return findFatherWhichIamInHisRight(head);
    }
    public static Node findRightMost(Node node) {
        while (node.right != null) {
            node = node.right;
        }
        return node;
    }

    public static Node findFatherWhichIamInHisRight(Node node) {
        while (node.parent != null && node.parent.right != node)
            node = node.parent;
        return node.parent;
    }
    public static void main(String[] args) {
        Node head = new Node(6);
        head.parent = null;
        head.left = new Node(3);
        head.left.parent = head;
        head.left.left = new Node(1);
        head.left.left.parent = head.left;
        head.left.left.right = new Node(2);
        head.left.left.right.parent = head.left.left;
        head.left.right = new Node(4);
        head.left.right.parent = head.left;
        head.left.right.right = new Node(5);
        head.left.right.right.parent = head.left.right;
        head.right = new Node(9);
        head.right.parent = head;
        head.right.left = new Node(8);
        head.right.left.parent = head.right;
        head.right.left.left = new Node(7);
        head.right.left.left.parent = head.right.left;
        head.right.right = new Node(10);
        head.right.right.parent = head.right;

        Node test = head.right.right; // 10
        System.out.println(test.value + " previous: " + findPrecursorNode(test).value);
        test = head.right; // 9
        System.out.println(test.value + " previous: " + findPrecursorNode(test).value);
        test = head.right.left; // 8
        System.out.println(test.value + " previous: " + findPrecursorNode(test).value);
        test = head.right.left.left; // 7
        System.out.println(test.value + " previous: " + findPrecursorNode(test).value);
        test = head; // 6
        System.out.println(test.value + " previous: " + findPrecursorNode(test).value);
        test = head.left.right.right; // 5
        System.out.println(test.value + " previous: " + findPrecursorNode(test).value);
        test = head.left.right; // 4
        System.out.println(test.value + " previous: " + findPrecursorNode(test).value);
        test = head.left; // 3
        System.out.println(test.value + " previous: " + findPrecursorNode(test).value);
        test = head.left.left.right; // 2
        System.out.println(test.value + " previous: " + findPrecursorNode(test).value);
        test = head.left.left; // 1's previous is null
        System.out.println(test.value + " previous: " + findPrecursorNode(test));
    }
}

3、判断一棵树是否为平衡/搜索/完全二叉树

套路:
列出可能性,定出返回值类型,假定左树能给我这样的类型,假定右树也能给我这样的类型,再做判断。由于是递归函数,最后要写返回给上一级的类型是如何生成的。
利用树的遍历过程中返回一个节点三次,遍历左边的过程收集左子树的信息(要什么信息就设计一个结构记录下来),遍历右边的过程收集右子树的信息,最后整合。

3.1 判断一棵树是否为平衡二叉树(AVL树)

package sword_to_offer_tree;

public class IsBalancedTree {

    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int value) {
            this.value = value;
        }
    }

    public static class ReturnData {
        public boolean isBalanced;
        public int height;

        public ReturnData(boolean isBalanced, int height) {
            this.isBalanced = isBalanced;
            this.height = height;
        }
    }

    public static ReturnData process(Node head) {
        if (head == null)
            return new ReturnData(true, 0);
        ReturnData leftData = process(head.left);
        ReturnData rightData = process(head.right);
        if (!leftData.isBalanced || !rightData.isBalanced || Math.abs(rightData.height - leftData.height) > 1) {
            return new ReturnData(false, 0);
        }
        return new ReturnData(true, Math.max(leftData.height, rightData.height) + 1);
    }

    public static boolean isBalancedTree(Node head) {
        return process(head).isBalanced;
    }

    public static void main(String[] args) {
        Node head = new Node(1);
        head.left = new Node(2);
        head.right = new Node(3);
        head.left.left = new Node(4);
        head.left.right = new Node(5);
        head.right.left = new Node(6);
        head.right.right = new Node(7);

        System.out.println(isBalancedTree(head));

    }
}

3.2 判断一棵树是否为搜索二叉树(BST,Binary Search Tree)

二叉树中序遍历的结果是依次升序的 <=> 该二叉树是一棵搜索二叉树

方法一:复用非递归的中序遍历,把打印该节点的值改成比较该节点的值是否比上一个节点的值大即可

package sword_to_offer_tree;

import java.util.Stack;

public class IsBSTReuseInorderTraversalUnRecur {
    // 复用非递归的中序遍历的函数
    // 二叉树中序遍历的结果是依次升序的 <=> 该二叉树是一棵搜索二叉树
    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int value) {
            this.value = value;
        }
    }

    // 用栈实现,当前节点不为空或者栈不为空继续:当前节点不为空,当前节点压入栈,当前节点往左跑(左边界一压压一溜);当前节点为空,从栈中拿一个打印,当前节点向右跑
    public static boolean isBST(Node head) {
        if (head == null) return true;
        int pre = Integer.MIN_VALUE;
        Stack<Node> stack = new Stack<>();
        while (head != null || !stack.isEmpty()) {
            if (head != null) {
                stack.push(head);
                head = head.left;
            } else {
                head = stack.pop();
                //System.out.print(head.value + " ");
                if (head.value > pre) {
                    pre = head.value;
                } else {
                    return false;
                }
                head = head.right;
            }
        }
        //System.out.println();
        return true;
    }

    // for LinkedListHasLoopOrNot -- print tree
    public static void printTree(Node head) {
        System.out.println("Binary Tree:");
        printInOrder(head, 0, "H", 17);
        System.out.println();
    }

    public static void printInOrder(Node head, int height, String to, int len) {
        if (head == null) {
            return;
        }
        printInOrder(head.right, height + 1, "v", len);
        String val = to + head.value + to;
        int lenM = val.length();
        int lenL = (len - lenM) / 2;
        int lenR = len - lenM - lenL;
        val = getSpace(lenL) + val + getSpace(lenR);
        System.out.println(getSpace(height * len) + val);
        printInOrder(head.left, height + 1, "^", len);
    }

    public static String getSpace(int num) {
        String space = " ";
        StringBuffer buf = new StringBuffer("");
        for (int i = 0; i < num; i++) {
            buf.append(space);
        }
        return buf.toString();
    }

    public static void main(String[] args) {
        Node head = new Node(4);
        head.left = new Node(2);
        head.right = new Node(6);
        head.left.left = new Node(1);
        head.left.right = new Node(3);
        head.right.left = new Node(5);

        printTree(head);
        System.out.println(isBST(head));
    }
}

方法二:复用查找后继节点的函数

package sword_to_offer_tree;

public class IsBSTReuseSuccessorNodeMethod {
    // 复用找到下一个节点的函数
    // 二叉树中序遍历的结果是依次升序的 <=> 该二叉树是一棵搜索二叉树
    public static class Node {
        public int value;
        public Node left;
        public Node right;
        public Node parent;

        public Node(int data) {
            this.value = data;
        }
    }

    // 若有右子树,则为右子树上最左的节点;若没有右子树,则为第一个满足某种要求的父节点,要求是我在该父节点的左子树上
    public static Node findSuccessorNode(Node head) {
        if (head == null) return null;
        if (head.right != null) return findLeftMostNode(head.right);
        else return findFatherWhichIamInHisLeft(head);
    }

    public static Node findLeftMostNode(Node node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }

    public static Node findFatherWhichIamInHisLeft(Node node) {
        Node parent = node.parent;
        while (parent != null) {
            if (parent.left == node) {
                return parent;
            } else {
                node = parent;
                parent = parent.parent;
            }
        }
        return parent;
    }

    public static boolean isBST(Node head) {
        Node successorNode = findSuccessorNode(head);
        while (head.value < successorNode.value && findSuccessorNode(successorNode) != null) {
            head = successorNode;
            successorNode = findSuccessorNode(head);
        }
        if (findSuccessorNode(successorNode) == null) return true;
        return false;
    }
    // for LinkedListHasLoopOrNot -- print tree
    public static void printTree(Node head) {
        System.out.println("Binary Tree:");
        printInOrder(head, 0, "H", 17);
        System.out.println();
    }

    public static void printInOrder(Node head, int height, String to, int len) {
        if (head == null) {
            return;
        }
        printInOrder(head.right, height + 1, "v", len);
        String val = to + head.value + to;
        int lenM = val.length();
        int lenL = (len - lenM) / 2;
        int lenR = len - lenM - lenL;
        val = getSpace(lenL) + val + getSpace(lenR);
        System.out.println(getSpace(height * len) + val);
        printInOrder(head.left, height + 1, "^", len);
    }

    public static String getSpace(int num) {
        String space = " ";
        StringBuffer buf = new StringBuffer("");
        for (int i = 0; i < num; i++) {
            buf.append(space);
        }
        return buf.toString();
    }

    public static void main(String[] args) {
        Node head = new Node(4);
        head.left = new Node(2);
        head.right = new Node(6);
        head.left.left = new Node(1);
        head.left.right = new Node(3);
        head.right.left = new Node(5);

        printTree(head);
        System.out.println(isBST(head));
    }
}

3.3 判断一棵树是否为完全二叉树

package sword_to_offer_tree;

import java.util.LinkedList;
import java.util.Queue;

public class IsCBT {
    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int data) {
            this.value = data;
        }
    }

    // 队列按层遍历
    // 1、有右孩子没有左孩子,一定不是完全二叉树
    // 2、左右孩子不双全:有左没右,或者左右都没有,(开启一个阶段)后面遇到的节点都必须是叶节点,否则不是完全二叉树
    // 若不违反1和2,则这棵树是完全二叉树
    public static boolean isCBT(Node head) {
        if (head == null) return true;
        Queue<Node> queue = new LinkedList<>();
        boolean leafStage = false;
        queue.offer(head);
        while (!queue.isEmpty()) {
            head = queue.poll();
            Node l = head.left;
            Node r = head.right;
            if ((r != null && l == null) || (leafStage && !(l == null && r == null))) {
                return false;
            }
            if (l != null) {
                queue.offer(l);
            }
            if (r != null) {
                queue.offer(r);
            } else {
                leafStage = true;
            }
        }
        return true;
    }

    // for LinkedListHasLoopOrNot -- print tree
    public static void printTree(Node head) {
        System.out.println("Binary Tree:");
        printInOrder(head, 0, "H", 17);
        System.out.println();
    }

    public static void printInOrder(Node head, int height, String to, int len) {
        if (head == null) {
            return;
        }
        printInOrder(head.right, height + 1, "v", len);
        String val = to + head.value + to;
        int lenM = val.length();
        int lenL = (len - lenM) / 2;
        int lenR = len - lenM - lenL;
        val = getSpace(lenL) + val + getSpace(lenR);
        System.out.println(getSpace(height * len) + val);
        printInOrder(head.left, height + 1, "^", len);
    }

    public static String getSpace(int num) {
        String space = " ";
        StringBuffer buf = new StringBuffer("");
        for (int i = 0; i < num; i++) {
            buf.append(space);
        }
        return buf.toString();
    }

    public static void main(String[] args) {
        Node head = new Node(4);
        head.left = new Node(2);
        head.right = new Node(6);
        head.left.left = null;
        head.left.right = new Node(3);
        head.right.left = new Node(5);

        printTree(head);
        System.out.println(isCBT(head));

    }
}

4、得到树的深度

递归:左右子树高度的大者 + 1
非递归:按层遍历的思路

package sword_to_offer_tree;

import java.util.LinkedList;
import java.util.Queue;

public class GetTreeDepth {
    public static class TreeNode {
        int value = 0;
        TreeNode left = null;
        TreeNode right = null;

        public TreeNode(int value) {
            this.value = value;

        }
    }

    // recursively
    public static int TreeDepth1(TreeNode root) {
        if (root == null) {
            return 0;
        }
        return Math.max(TreeDepth1(root.left), TreeDepth1(root.right)) + 1;
    }

    // unrecursively
    // count为该层从队列中弹出的节点的个数,nextLayerCount为在队列中的元素个数,即下一层的节点的总个数
    public static int TreeDepth2(TreeNode root) {
        if (root == null) {
            return 0;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int depth = 0, count = 0, nextLayerCount = 1;
        while (!queue.isEmpty()) {
            root = queue.poll();
            count++;
            if (root.left != null) {
                queue.offer(root.left);
            }
            if (root.right != null) {
                queue.offer(root.right);
            }
            if (count == nextLayerCount) {
                nextLayerCount = queue.size();
                count = 0;
                depth++;
            }
        }
        return depth;
    }

    public static void printTree(TreeNode root) {
        System.out.println("Binary Tree:");
        printInOrder(root, 0, "H", 17);
        System.out.println();
    }

    public static void printInOrder(TreeNode root, int height, String to, int len) {
        if (root == null) {
            return;
        }
        printInOrder(root.right, height + 1, "v", len);
        String value = to + root.value + to;
        int lenM = value.length();
        int lenL = (len - lenM) / 2;
        int lenR = len - lenM - lenL;
        value = getSpace(lenL) + value + getSpace(lenR);
        System.out.println(getSpace(height * len) + value);
        printInOrder(root.left, height + 1, "^", len);
    }

    public static String getSpace(int num) {
        String space = " ";
        StringBuffer buf = new StringBuffer("");
        for (int i = 0; i < num; i++) {
            buf.append(space);
        }
        return buf.toString();
    }


    public static void main(String[] args) {
        TreeNode root = new TreeNode(5);
        root.left = new TreeNode(3);
        root.right = new TreeNode(8);
        root.left.left = new TreeNode(2);
        root.left.right = new TreeNode(4);
        root.left.left.left = new TreeNode(1);
        root.right.left = new TreeNode(7);
        root.right.left.left = new TreeNode(6);
        root.right.right = new TreeNode(10);
        root.right.right.left = new TreeNode(9);
        root.right.right.right = new TreeNode(11);
        printTree(root);
        System.out.println(TreeDepth1(root));
        System.out.println(TreeDepth2(root));
    }
}

5、按层遍历打印树的变体

package sword_to_offer_tree;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class PrintTreeFromTopToBottom {
    public static class TreeNode {
        int value = 0;
        TreeNode left = null;
        TreeNode right = null;

        public TreeNode(int value) {
            this.value = value;
        }
    }

    public static void printArrayList(ArrayList<Integer> arrayList) {
        Integer[] array = arrayList.toArray(new Integer[arrayList.size()]);
        for (Integer i : array) {
            System.out.print(i + " ");
        }
        System.out.println();
    }

    public static void printDoubleArrayList(ArrayList<ArrayList<Integer>> arrayLists) {
        for (ArrayList<Integer> arrayList : arrayLists) {
            for (Integer i : arrayList) {
                System.out.print(i + " ");
            }
            System.out.println();
        }
    }

    public static ArrayList<Integer> getArrayListFromTopToBottom(TreeNode root) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        if (root == null) return arrayList;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode treeNode = queue.poll();
            arrayList.add(treeNode.value);
            if (treeNode.left != null) {
                queue.offer(treeNode.left);
            }
            if (treeNode.right != null) {
                queue.offer(treeNode.right);
            }
        }
        return arrayList;
    }

    public static void printFromTopToBottom(TreeNode root) {
        if (root == null) return;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode treeNode = queue.poll();
            System.out.print(treeNode.value + " ");
            if (treeNode.left != null) {
                queue.offer(treeNode.left);
            }
            if (treeNode.right != null) {
                queue.offer(treeNode.right);
            }
        }
        System.out.println();
    }

    // count为该层从队列中弹出的节点的个数,nextLayerCount为在队列中的元素个数,即下一层的节点的总个数
    public static void printFromTopToBottomWithChangeLine(TreeNode root) {
        if (root == null) return;
        Queue<TreeNode> queue = new LinkedList<>();
        int count = 0;
        int nextLayerCount = 1;
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode treeNode = queue.poll();
            count++;
            System.out.print(treeNode.value + " ");
            if (treeNode.left != null) {
                queue.offer(treeNode.left);
            }
            if (treeNode.right != null) {
                queue.offer(treeNode.right);
            }
            if (count == nextLayerCount) {
                System.out.println();
                count = 0;
                nextLayerCount = queue.size();
            }
        }
    }

    public static ArrayList<ArrayList<Integer>> getDoubleArrayFromTopToBottomWithChangeLine(TreeNode root) {
        ArrayList<ArrayList<Integer>> arrayLists = new ArrayList<>();
        if (root == null) return arrayLists;
        Queue<TreeNode> queue = new LinkedList<>();
        ArrayList<Integer> layerList = new ArrayList<>();
        int count = 0;
        int nextLayerCount = 1;
        queue.add(root);
        while (!queue.isEmpty()) {
            TreeNode treeNode = queue.poll();
            layerList.add(treeNode.value);
            count++;
            if (treeNode.left != null) {
                queue.add(treeNode.left);
            }
            if (treeNode.right != null) {
                queue.add(treeNode.right);
            }
            if (count == nextLayerCount) {
                arrayLists.add(layerList);
                count = 0;
                nextLayerCount = queue.size();
                layerList = new ArrayList<>();
            }
        }
        return arrayLists;
    }

    public static void printTree(TreeNode root) {
        System.out.println("Binary Tree:");
        printInOrder(root, 0, "H", 17);
        System.out.println();
    }

    public static void printInOrder(TreeNode root, int height, String to, int len) {
        if (root == null) {
            return;
        }
        printInOrder(root.right, height + 1, "v", len);
        String val = to + root.value + to;
        int lenM = val.length();
        int lenL = (len - lenM) / 2;
        int lenR = len - lenM - lenL;
        val = getSpace(lenL) + val + getSpace(lenR);
        System.out.println(getSpace(height * len) + val);
        printInOrder(root.left, height + 1, "^", len);
    }

    public static String getSpace(int num) {
        String space = " ";
        StringBuffer buf = new StringBuffer("");
        for (int i = 0; i < num; i++) {
            buf.append(space);
        }
        return buf.toString();
    }


    public static void main(String[] args) {
        TreeNode root = new TreeNode(5);
        root.left = new TreeNode(3);
        root.right = new TreeNode(8);
        root.left.left = new TreeNode(2);
        root.left.right = new TreeNode(4);
        root.left.left.left = new TreeNode(1);
        root.right.left = new TreeNode(7);
        root.right.left.left = new TreeNode(6);
        root.right.right = new TreeNode(10);
        root.right.right.left = new TreeNode(9);
        root.right.right.right = new TreeNode(11);
        printTree(root);
        System.out.println("printArrayList(getArrayListFromTopToBottom(root)): ");
        printArrayList(getArrayListFromTopToBottom(root));
        System.out.println("printFromTopToBottom(root): ");
        printFromTopToBottom(root);
        System.out.println("printFromTopToBottomWithChangeLine(root): ");
        printFromTopToBottomWithChangeLine(root);
        System.out.println("printDoubleArrayList(getDoubleArrayFromTopToBottomWithChangeLine(root)): ");
        printDoubleArrayList(getDoubleArrayFromTopToBottomWithChangeLine(root));
    }
}

6、二叉树的对称问题

6.1 将二叉树改成自己的镜像

package sword_to_offer_tree;

import java.util.Stack;

public class MirrorOfBinaryTree {
    public static class TreeNode {
        int value = 0;
        TreeNode left = null;
        TreeNode right = null;

        public TreeNode(int value) {
            this.value = value;
        }
    }

    // recursively
    public static void Mirror1(TreeNode root) {
        if (root == null) return;

        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;

        if (root.left != null) {
            Mirror1(root.left);
        }
        if (root.right != null) {
            Mirror1(root.right);
        }
    }

    // unrecursively
    // 手动压栈弹栈,先换下层再换上层 -> 弹栈时要求先弹出下层节点再弹出上层节点 -> 先将上层压栈后再将下层压栈
    public static void Mirror2(TreeNode root) {
        if (root == null) return;
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode treeNode = stack.pop();
            if (treeNode.left != null || treeNode.right != null) {
                TreeNode tmp = treeNode.left;
                treeNode.left = treeNode.right;
                treeNode.right = tmp;
            }
            if (treeNode.left != null) {
                stack.push(treeNode.left);
            }
            if (treeNode.right != null) {
                stack.push(treeNode.right);
            }
        }
    }

    public static void printTree(TreeNode root) {
        //System.out.println("Binary Tree:");
        printInOrder(root, 0, "H", 17);
        System.out.println();
    }

    public static void printInOrder(TreeNode root, int height, String to, int len) {
        if (root == null) {
            return;
        }
        printInOrder(root.right, height + 1, "v", len);
        String val = to + root.value + to;
        int lenM = val.length();
        int lenL = (len - lenM) / 2;
        int lenR = len - lenM - lenL;
        val = getSpace(lenL) + val + getSpace(lenR);
        System.out.println(getSpace(height * len) + val);
        printInOrder(root.left, height + 1, "^", len);
    }

    public static String getSpace(int num) {
        String space = " ";
        StringBuffer buf = new StringBuffer("");
        for (int i = 0; i < num; i++) {
            buf.append(space);
        }
        return buf.toString();
    }

    public static void main(String[] args) {
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(-222222222);
        root.right = new TreeNode(3);
        root.left.left = new TreeNode(Integer.MIN_VALUE);
        root.right.left = new TreeNode(55555555);
        root.right.right = new TreeNode(66);
        root.left.left.right = new TreeNode(777);
        System.out.println("before Mirror1: ");
        printTree(root);
        Mirror2(root);
        System.out.println("after Mirror1: ");
        printTree(root);

        root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(3);
        root.left.left = new TreeNode(4);
        root.right.left = new TreeNode(5);
        root.right.right = new TreeNode(6);
        root.left.left.right = new TreeNode(7);
        System.out.println("before Mirror1: ");
        printTree(root);
        Mirror2(root);
        System.out.println("after Mirror1: ");
        printTree(root);

        root = new TreeNode(1);
        root.left = new TreeNode(1);
        root.right = new TreeNode(1);
        root.left.left = new TreeNode(1);
        root.right.left = new TreeNode(1);
        root.right.right = new TreeNode(1);
        root.left.left.right = new TreeNode(1);
        System.out.println("before Mirror1: ");
        printTree(root);
        Mirror2(root);
        System.out.println("after Mirror1: ");
        printTree(root);
    }
}

6.2 判断一棵二叉树是否是对称的

package sword_to_offer_tree;

public class IsSymmetricalTree {
    public static class TreeNode {
        int value = 0;
        TreeNode left = null;
        TreeNode right = null;

        public TreeNode(int value) {
            this.value = value;
        }
    }

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

    // 对称位置相等
    private static boolean isSymmetrical(TreeNode left, TreeNode right) {
        if (left == null && right == null) return true;
        if (left == null || right == null) return false;
        if (left.value != right.value) return false;
        return isSymmetrical(left.right, right.left) && isSymmetrical(left.left, right.right);
    }

    public static void printTree(TreeNode root) {
        System.out.println("Binary Tree:");
        printInOrder(root, 0, "H", 17);
        System.out.println();
    }

    public static void printInOrder(TreeNode root, int height, String to, int len) {
        if (root == null) {
            return;
        }
        printInOrder(root.right, height + 1, "v", len);
        String val = to + root.value + to;
        int lenM = val.length();
        int lenL = (len - lenM) / 2;
        int lenR = len - lenM - lenL;
        val = getSpace(lenL) + val + getSpace(lenR);
        System.out.println(getSpace(height * len) + val);
        printInOrder(root.left, height + 1, "^", len);
    }

    public static String getSpace(int num) {
        String space = " ";
        StringBuffer buf = new StringBuffer("");
        for (int i = 0; i < num; i++) {
            buf.append(space);
        }
        return buf.toString();
    }

    public static void main(String[] args) {
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(-222222222);
        root.right = new TreeNode(3);
        root.left.left = new TreeNode(Integer.MIN_VALUE);
        root.right.left = new TreeNode(55555555);
        root.right.right = new TreeNode(66);
        root.left.left.right = new TreeNode(777);
        printTree(root);
        System.out.println(isSymmetrical(root));
        System.out.println("=============================");

        root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(2);
        root.left.left = new TreeNode(4);
        root.right.left = new TreeNode(5);
        root.right.right = new TreeNode(4);
        root.left.right = new TreeNode(5);
        printTree(root);
        System.out.println(isSymmetrical(root));
        System.out.println("==============================");

        root = new TreeNode(1);
        root.left = new TreeNode(1);
        root.right = new TreeNode(1);
        root.left.left = new TreeNode(1);
        root.right.left = new TreeNode(1);
        root.right.right = new TreeNode(1);
        root.left.left.right = new TreeNode(1);
        printTree(root);
        System.out.println(isSymmetrical(root));
        System.out.println("==============================");
    }
}

7、判断B树是否是A树的子结构

规定:空树不是任何树的子结构

package sword_to_offer_tree;

// 输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
public class TreeBIsSubtreeOfTreeAOrNot {
    public static class TreeNode {
        int value = 0;
        TreeNode left = null;
        TreeNode right = null;

        public TreeNode(int value) {
            this.value = value;
        }
    }

    public static boolean isSubtree(TreeNode root1, TreeNode root2) {
        if (root1 == null || root2 == null) return false;
        boolean res = isSameOrMore(root1, root2);
        if (!res) {
            res = isSameOrMore(root1.left, root2);
        }
        if (!res) {
            res = isSameOrMore(root1.right, root2);
        }
        return res;
    }

    public static boolean isSameOrMore(TreeNode root1, TreeNode root2) {
        // root2子树已经遍历完了,true
        if (root2 == null) return true;
        // root1母树已经遍历完了但root2子树没有遍历完,false
        if (root1 == null) return false;

        if (root1.value != root2.value) return false;
        return isSameOrMore(root1.left, root2.left) && isSameOrMore(root1.right, root2.right);
    }

    public static void printTree(TreeNode head) {
        System.out.println("Binary Tree:");
        printInOrder(head, 0, "H", 17);
        System.out.println();
    }

    public static void printInOrder(TreeNode head, int height, String to, int len) {
        if (head == null) {
            return;
        }
        printInOrder(head.right, height + 1, "v", len);
        String value = to + head.value + to;
        int lenM = value.length();
        int lenL = (len - lenM) / 2;
        int lenR = len - lenM - lenL;
        value = getSpace(lenL) + value + getSpace(lenR);
        System.out.println(getSpace(height * len) + value);
        printInOrder(head.left, height + 1, "^", len);
    }

    public static String getSpace(int num) {
        String space = " ";
        StringBuffer buf = new StringBuffer("");
        for (int i = 0; i < num; i++) {
            buf.append(space);
        }
        return buf.toString();
    }

    public static void main(String[] args) {
        TreeNode root1 = new TreeNode(1);
        root1.left = new TreeNode(2);
        root1.right = new TreeNode(3);
        root1.left.left = new TreeNode(4);
        root1.left.right = new TreeNode(5);
        root1.right.left = new TreeNode(6);
        root1.right.right = new TreeNode(7);

        TreeNode root2 = new TreeNode(3);
        root2.left = new TreeNode(6);
        root2.right = new TreeNode(7);

        System.out.println("root1: ");
        printTree(root1);
        System.out.println("root2: ");
        printTree(root2);

        System.out.println(isSubtree(root1, root2));

        root1 = new TreeNode(8);
        root1.left = new TreeNode(8);
        root1.right = new TreeNode(7);
        root1.left.left = new TreeNode(9);
        root1.left.right = new TreeNode(2);
        root1.left.right.left = new TreeNode(4);
        root1.left.right.right = new TreeNode(7);

        root2 = new TreeNode(8);
        root2.left = new TreeNode(9);
        root2.right = new TreeNode(2);

        System.out.println("root1: ");
        printTree(root1);
        System.out.println("root2: ");
        printTree(root2);

        System.out.println(isSubtree(root1, root2));
    }
}

8、判断一个序列是否为某棵树的后序遍历序列

package sword_to_offer_tree;

/*输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。
  如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。*/

public class IsPosTraversalSequenceOfBSTOrNot {
    /*BST的后序序列的合法序列是,对于一个序列S,最后一个元素是x (也就是根),
      如果去掉最后一个元素的序列为T,那么T满足:
      T可以分成两段,前一段(左子树)小于x,后一段(右子树)大于x,
      且这两段(子树)都是合法的后序序列。完美的递归定义。*/
    public static boolean isPosTraversalSequenceOfBST(int[] sequence) {
        if (sequence == null || sequence.length < 1) return false;
        return isPos(sequence, 0, sequence.length - 1);
    }

    public static boolean isPos(int[] sequence, int start, int end) {
        if (start >= end) return true;
        int i = start;
        // 如果是后序序列则start~i-1为小于sequence[end]的数,i~end-1为大于sequence[end]的数
        while (i < end && sequence[i] < sequence[end]) {
            i++;
        }
        // 验证i~end-1为大于sequence[end]的数
        for (int j = i; j < end; j++) {
            if (sequence[j] < sequence[end])
                return false;
        }
        return isPos(sequence, start, i - 1) && isPos(sequence, i, end - 1);
    }

    public static void main(String[] args) {
        int[] sequence = new int[]{7,4,6,5};
        System.out.println(isPosTraversalSequenceOfBST(sequence));
    }

}

阅读更多
上一篇.xml文件中的&quot;&amp;&quot;报错:Unescaped &amp; or nonterminated character/entity reference
下一篇JDK9 HashMap源码阅读笔记
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭