二叉树基础题目

目录

二叉树非递归先序遍历

二叉树非递归后序遍历

二叉树非递归中序遍历

二叉树层序遍历

求二叉树的最大宽度

判断当前二叉树是否搜索二叉树

解法一

解法二

判断当前二叉树是否完全二叉树

判断当前二叉树是否平衡二叉树

判断当前二叉树是否满二叉树

给定二叉树的头节点与两个节点,返回最低公共节点

折纸问题


二叉树非递归先序遍历

先序遍历:二叉树中每个子树都以头-左-右的顺序打印。

思路:

1.头节点入栈;

2.弹出栈中节点,同时将子节点从右至左入栈;

3.继续弹出节点,每弹出一个节点执行第二步操作。

    //实体类
    public static class Node {
        public int value;
        public Node left;
        public Node right;
        public Node(int data){
            this.value = data;
        }
    }
    
    public static void preOrderUnRecur(Node head) {
        System.out.println("pre-order:");
        if (head != null) {
            Stack<Node> stack = new Stack<Node>();
            stack.add(head);
            while (!stack.isEmpty()) {
                head = stack.pop();
                System.out.println(head.value + "  ");
                if (head.right != null){
                    stack.push(head.right);
                }
                if (head.left != null) {
                    stack.push(head.left);
                }
            }
        }
        System.out.println();
    }

二叉树非递归后序遍历

后序遍历:二叉树中每个子树都以右-左-头的顺序打印。

利用栈的特性,将上一题的结果入栈后依次弹出即可。

    public static void posOrderUnRecur1(Node head) {
        System.out.println("poe-order:");
        if (head != null) {
            Stack<Node> s1 = new Stack<Node>();
            Stack<Node> s2 = new Stack<Node>();
            s1.push(head);
            while (!s1.isEmpty()) {
                head = s1.pop();
                s2.push(head);
                if (head.left != null){
                    s1.push(head.right);
                }
                if (head.right != null) {
                    s1.push(head.left);
                }
            }
            while (s2 != null) {
                System.out.println(s2.pop().value + "  ");
            }
        }
        System.out.println();
    }

二叉树非递归中序遍历

中序遍历:二叉树每个子树都以左-头-右的顺序打印。

思路:

1.将二叉树左边界从头节点开始依次入栈。

2.弹出栈中节点,每弹出一个节点时查看其是否存在子节点,如果有,入栈。

3.每个节点入栈时都将以该节点为头的二叉树左边界依次入栈。

4.重复执行2、3步骤,周而复始,直至栈空。

    public static void inOrderUnRecur(Node head) {
        System.out.println("in-order:");
        if (head != null) {
            Stack<Node> stack = new Stack<Node>();
            stack.push(head);
            while (!stack.isEmpty() || head != null) {
                if (head != null) {
                    stack.push(head);
                    head = head.left;
                }else {
                    head = stack.pop();
                    System.out.println(head.value + "  ");
                    head = head.right;
                }
            }
        }
        System.out.println();
    }

二叉树层序遍历

层序遍历(宽度优先遍历):二叉树遍历完一层再遍历下一层。

思路:

1.头节点入队列。

2.弹出节点,每弹出一个节点,将其子节点入栈。

3.重复第二部操作。

    public static void levelOrder(Node head) {
        if (head == null) {
            return;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(head);
        while (!queue.isEmpty()) {
            Node cur = queue.poll();
            System.out.println(cur.value);
            if (head.left != null) {
                queue.add(head.left);
            }
            if (cur.right != null) {
                queue.add(cur.right);
            }
        }
    }

求二叉树的最大宽度

在层序遍历的基础上记录每一层的节点数取最大值。

    public static void maxWidth(Node head) {
        if (head == null) {
            return;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(head);
        HashMap<Node, Integer> levelMap = new HashMap<>();
        levelMap.put(head, 1);
        int curLevel = 1;
        int curlevelNodes = 0;
        int max = Integer.MIN_VALUE;
        while (!queue.isEmpty()) {
            Node cur = queue.poll();
            int curNodeLevel = levelMap.get(cur);
            if (curNodeLevel == curLevel) {
                curlevelNodes++;
            }else {
                max = Math.max(curlevelNodes, max);
                curLevel++;
                curlevelNodes = 1;
            }
            System.out.println(cur.value);
            if (head.left != null) {
                levelMap.put(cur.left, curNodeLevel+1);
                queue.add(head.left);
            }
            if (cur.right != null) {
                levelMap.put(cur.right, curNodeLevel+1);
                queue.add(cur.right);
            }
        }
    }

判断当前二叉树是否搜索二叉树

搜索二叉树:对于每一颗子树来说,它的左树都比它小,右树都比它大。

解法一

中序遍历,遍历时比较当前节点值是否大于上一节点值,如果不大于,则不为搜索二叉树。

    private static int preValue = Integer.MIN_VALUE;
    
    public static boolean isBst(Node head) {
        if (head == null) {
            return true;
        }
        boolean isLeftBst = isBst(head.left);
        if (!isLeftBst) {
            return false;
        }
        if (head.value <= preValue) {
            return false;
        }else {
            preValue = head.value;
        }
        return isBst(head.right);
    }

解法二

递归解法(树形DP)

    public static boolean isBstRecu(Node head) {
        if (head == null) {
            return true;
        }
        return processBst(head).isBst;
    }

    public static class ReturnTypeBst {
        public boolean isBst;
        public int min;
        public int max;

        public ReturnTypeBst(boolean isBst, int min, int max) {
            this.isBst = isBst;
            this.min = min;
            this.max = max;
        }
    }

    private static ReturnTypeBst processBst(Node x) {
        if (x == null) {
            return null;
        }
        ReturnTypeBst leftData = processBst(x.left);
        ReturnTypeBst rightData = processBst(x.right);
        int max = x.value;
        int min = x.value;
        if (leftData != null) {
            min = Math.min(min, leftData.min);
            max = Math.max(max, leftData.max);
        }
        if (rightData != null) {
            min = Math.min(min, rightData.min);
            max = Math.max(max, rightData.max);
        }
        boolean isBst = true;
        if ((leftData != null && (!leftData.isBst || leftData.max >= x.value)) ||
                (rightData != null && (!rightData.isBst || rightData.min <= x.value))) {
            isBst = false;
        }
        return new ReturnTypeBst(isBst, min, max);
    }

判断当前二叉树是否完全二叉树

完全二叉树:将二叉树各节点按顺序编号,若其每个节点的编号与满二叉树的编号相同,则为完全二叉树。

思路:

1.层序遍历。

2.是否存在有右无左的节点,若存在,false。

3.当发现某一结点左右子节点不双全时,层序遍历中的后续节点必须为叶子节点,若不是,false。

    public static boolean isCbt(Node head) {
        if (head == null) {
            return true;
        }
        LinkedList<Node> queue = new LinkedList<>();
        //是否遇到过左右两个孩子不双全的节点
        boolean leaf = false;
        Node left = null;
        Node right = null;
        queue.add(head);
        while (!queue.isEmpty()) {
            head = queue.poll();
            left = head.left;
            right = head.right;
            if (
                    (leaf && (left != null || right != null))
                    || (left == null && right != null)
                ) {
                return false;
            }
            if (left != null) {
                queue.add(left);
            }
            if (right != null) {
                queue.add(right);
            }
            if (left == null || right == null) {
                leaf = true;
            }
        }
        return true;

判断当前二叉树是否平衡二叉树

平衡二叉树:每个节点的左树与右树高度差不超过1。

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

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

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

    private static ReturnType process(Node x) {
        if (x == null) {
            return new ReturnType(true, 0);
        }
        ReturnType leftDate = process(x.left);
        ReturnType rightDate = process(x.right);
        int height = Math.max(leftDate.height,rightDate.height) + 1;
        boolean isBalanced = leftDate.isBalanced && rightDate.isBalanced
                && Math.abs(leftDate.height - rightDate.height) < 2;
        return new ReturnType(isBalanced, height);
    }

判断当前二叉树是否满二叉树

public static boolean isFullRecu(Node head) {
        if (head == null) {
            return true;
        }
        ReturnTypeFull res =  processFull(head);
        //深度为k,节点数为n的满二叉树满足 2的k次方-1 == n
        return res.nodes == (1 << res.height - 1);
    }

    public static class ReturnTypeFull {
        public int height;
        public int nodes;

        public ReturnTypeFull(int height, int nodes) {
            this.height = height;
            this.nodes = nodes;
        }
    }

    private static ReturnTypeFull processFull(Node x) {
        if (x == null) {
            return new ReturnTypeFull(0,0);
        }
        ReturnTypeFull leftData = processFull(x.left);
        ReturnTypeFull rightData = processFull(x.right);
        int height = Math.max(leftData.height, rightData.height) + 1;
        int nodes = leftData.nodes + rightData.nodes + 1;
        return new ReturnTypeFull(height, nodes);
    }

给定二叉树的头节点与两个节点,返回最低公共节点

    public static Node lca(Node head, Node o1, Node o2) {
        if (head == null || head == o1 || head == o2) {
            return head;
        }
        Node left = lca(head.left, o1, o2);
        Node right = lca(head.right, o1, o2);
        if (left != null && right != null) {
            return head;
        }
        return left != null ? left : right;
    }

折纸问题

  • 准备一个纸条,从纸条的下边向上方对折一次,压出折痕后展开。
  •  此时折痕时凹下去的,即折痕突起的方向指向纸条的背面。
  • 给定一个输入参数N,代表纸条都从下边向上方连续对着N次。
  • 要求从上到下打印所有折痕的方向。

思路:

  • 将折痕视为一颗二叉树,对折次数为二叉树深度。
  • 每个节点的左子节点为凹痕节点,右子节点为凸痕节点。
    public static void printAllFolds(int n) {
        printProcess(1, n, true);
    }

    private static void printProcess(int i, int n, boolean down) {
        if (i > n) {
            return;
        }
        printProcess(i + 1, n, true);
        System.out.println(down ? "凹" : "凸");
        printProcess(i + 1, n, false);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值