lettcode 二叉树(递归,非递归遍历,判断是否是平衡,搜索,满,完全二叉树)

Node

/**
 * @author Xjl
 * @date 2022/5/10 13:27
 */
public class Node {
    public int val;
    public Node left;
    public Node right;

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

    public Node(int val, Node left, Node right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }

    @Override
    public String toString() {
        return "Node{" +
                "val=" + val +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Node node = (Node) o;
        return val == node.val &&
                Objects.equals(left, node.left) &&
                Objects.equals(right, node.right);
    }

    @Override
    public int hashCode() {
        return Objects.hash(val, left, right);
    }
}

相关代码

import sun.plugin.viewer.LifeCycleManager;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Stack;

/**
 * @author Xjl
 * @date 2022/5/10 13:33
 */
public class TestNode {

    /**
     * 递归写法
     */
    public void preOrder(Node node) {
        if (node == null) {
            return;
        }
        System.out.println(node);
        preOrder(node.left);
        preOrder(node.right);
    }

    public void order(Node node) {
        if (node == null) {
            return;
        }
        order(node.left);
        System.out.println(node);
        order(node.right);
    }

    public void lastOrder(Node node) {
        if (node == null) {
            return;
        }
        lastOrder(node.left);
        lastOrder(node.right);
        System.out.println(node);
    }

    /**
     * 非递归写法
     */
    public void preOrderUnRecur(Node node) {
        if (node != null) {
            Stack<Node> nodes = new Stack<>();
            nodes.push(node);
            while (!nodes.isEmpty()) {
                node = nodes.pop();
                System.out.println(node);
                if (node.right != null) {
                    nodes.push(node.right);
                }
                if (node.left != null) {
                    nodes.push((node.left));
                }
            }
        }
    }

    /**
     * 先将最左边的节点入栈 ,然后一次弹出,打印,判断是否有其右节点
     * @param head
     */
    public void orderUnRecur(Node head) {
        if (head != null) {
            Stack<Node> nodes = new Stack<>();
            while (!nodes.isEmpty() || head != null) {
                if (head != null) {
                    nodes.push(head);
                    head = head.left;
                } else {
                    head = nodes.pop();
                    System.out.println(head + " ");
                    head = head.right;
                }
            }
        }
    }

    /**
     * 广度遍历 使用队列
     * @param head
     * @return
     */
    public int width(Node head) {
        if (head == null) {
            return 0;
        }
        LinkedList<Node> queue = new LinkedList<>();
        queue.add(head);
        HashMap<Node, Integer> map = new HashMap<>();
        map.put(head, 1);
        int curLevel = 1;
        int curLevelNodes = 0;
        int max = Integer.MIN_VALUE;
        while (!queue.isEmpty()) {
            head = queue.poll();
            int curNodeLevel = map.get(head);
            if (curLevel == curNodeLevel) {
                curLevelNodes++;
            } else {
                max = Math.max(max, curLevelNodes);
                curLevel++;
                curLevelNodes = 1;
            }
            if (head.left != null) {
                map.put(head.left, curNodeLevel + 1);
                queue.add(head.left);
            }
            if (head.right != null) {
                map.put(head.right, curNodeLevel + 1);
                queue.add(head.right);
            }
        }
        return Math.max(max, curLevelNodes);
    }

    public void lastOrderUnRecur(Node node) {
        if (node != null) {
            Stack<Node> node1 = new Stack<>();
            Stack<Node> node2 = new Stack<>();
            node1.push(node);
            while (!node1.isEmpty()) {
                node = node1.pop();
                node2.push(node);
                if (node.left != null) {
                    node1.push(node.left);
                }
                if (node.right != null) {
                    node1.push(node.right);
                }
            }
            while (!node2.isEmpty()) {
                System.out.println(node2.pop() + " ");
            }
        }
    }

    /**
     * 搜索二叉树 : 每一棵子树的左边都比根节点小,右边都比根节点大。
     * 方法一
     * 判断一棵树 是否是搜索二叉树。 使用中序遍历 为升序 true 否则 false
     * @param head
     */
    public boolean isBinarySearchTree(Node head) {
        if (head != null) {
            int preVal = Integer.MIN_VALUE;
            Stack<Node> stack = new Stack<>();
            while (!stack.isEmpty() || head != null) {
                //左边界全部进栈
                if (head != null) {
                    stack.push(head);
                    head = head.left;
                } else {
                    head = stack.pop();
                    //小于前一个值 则不是升序。否则preVal = 当前值
                    if (head.val <= preVal) {
                        return false;
                    } else {
                        preVal = head.val;
                    }
                    head = head.right;
                }
            }
        }
        return true;
    }
    /**
     * 方法二
     * 二叉树dp
     */
    public static class ReturnDataOfSearch{
        int max;
        int min;
        boolean isSearchBinaryTree;

        public ReturnDataOfSearch(int max, int min, boolean isSearchBinaryTree) {
            this.max = max;
            this.min = min;
            this.isSearchBinaryTree = isSearchBinaryTree;
        }
    }
    
    public boolean isBinarySearchTree2(Node root){
        return process3(root).isSearchBinaryTree;
    }

    /**
     * 判读是否为搜索二叉树
     * @param root
     * @return
     */
    private ReturnDataOfSearch process3(Node root) {
        if (root == null){
            return null;
        }
        ReturnDataOfSearch left = process3(root.left);
        ReturnDataOfSearch right = process3(root.right);
        boolean isBST = true;
        if (left!=null && (!left.isSearchBinaryTree || left.max >= root.val)){
            isBST = false;
        }
        if (right!=null&& (!right.isSearchBinaryTree|| right.min <= root.val)){
            isBST = false;
        }
        int max = root.val;
        int min = root.val;
        if (left!=null){
            min = Math.min(min,left.min);
            max = Math.max(max,left.max);
        }
        if (right!=null){
            min = Math.min(min,right.min);
            max = Math.max(max,right.max);
        }
        return new  ReturnDataOfSearch(max,min,isBST);

    }

    /**
     * 二叉搜索树的最近公共祖先
     *  1 root=null 就没有
     *  2 root=o1 说明o1就是最近公共祖先
     *  3 root=o2 说明o2就是最近公共祖先
     *  从最后一层节点开始往上推,
     *  左空右空,返回null;
     *  左空右不空,返回o1或者o2
     *  左右都不空 说明本节点就是最近公共祖先
     * @param root 根节点
     * @param o1 随机节点
     * @param o2 随机节点
     * @return 最近公共祖先
     */
    public Node lowestCommonAncestor(Node root, Node o1, Node o2) {
        //最基本的三种情况
        if (root == null || root == o1 || root == o2) {
            return root;
        }
        Node left = lowestCommonAncestor(root.left, o1, o2);
        Node right = lowestCommonAncestor(root.right, o1, o2);
        if (left != null && right != null) {
            return root;
        }
        return left != null ? left : right;
    }


    /**
     * 完全二叉树 : 从第一层到倒数第二层全部都是满的,最后一层即便不是满的,也需要从左往右依次变满。
     * 如何判断 : 宽度遍历。(广度遍历)
     * 两种情况:
     * 1 任意节点有右孩子,没有左孩子,不是完全二叉树。
     * 2 在1条件满足的情况下,遇到了第一个节点左右孩子不双全,后续节点都应该为叶子节点。否则不是完全二叉树。
     * @param head
     * @return
     */
    public boolean isCompleteBinaryTree(Node head) {
        if (head != null) {
            boolean leaf = false;
            LinkedList<Node> nodes = new LinkedList<>();
            nodes.add(head);
            while (!nodes.isEmpty()) {
                head = nodes.poll();
                Node left = head.left;
                Node right = head.right;
                //leaf为true的话,说明后续节点必须为叶子节点。
                if (leaf && (left != null || right != null) || (left == null && right != null)) {
                    return false;
                }
                if (left != null) {
                    nodes.add(left);
                }
                if (right != null) {
                    nodes.add(right);
                }
                // 节点左右孩子不全,后续节点必须是叶子节点
                if (left == null || right == null) {
                    leaf = true;
                }

            }
        }
        return true;
    }
    /**
     * 方法2 广度遍历 ,若遇到为空之后,还有节点 返回false
     * @param head
     * @return
     */
    public boolean isCompleteBinaryTree2(Node head) {
        if (head != null) {
            boolean flag = false;
            LinkedList<Node> nodes = new LinkedList<>();
            nodes.add(head);
            while (!nodes.isEmpty()) {
                head = nodes.poll();
                if (head == null) {
                    //后续还有节点,直接返回false;
                    flag = true;
                } else {
                    if (flag) {
                        return false;
                    }
                    nodes.add(head.left);
                    nodes.add(head.right);
                }
            }
        }
        return true;
    }

    /**
     * 满二叉树: 满足 节点个数= 2^高度  -  1;
     * 判断是否是满二叉树
     * 树形dp  (dp:动态规划)
     */
    public static class Info {
        int nodes;
        int height;

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

    public boolean isFullBinaryTree(Node root) {
        if (root == null) {
            return true;
        }
        Info info = process(root);
        //加减法优先级高于位运算 所以加括号
        return info.nodes == ((1 << info.height) - 1);
    }

    private Info process(Node root) {
        if (root == null) {
            return new Info(0, 0);
        }
        Info leftData = process(root.left);
        Info rightData = process(root.right);
        int nodes = leftData.nodes + rightData.nodes + 1;
        int height = Math.max(leftData.height, rightData.height) + 1;
        return new Info(nodes, height);
    }


    /**
     * 平衡二叉树 左右子树高度差不超过2
     * 如何判断:dp 对于每颗子树来讲,左边平衡 右边平衡,并且|左子树高度-右子树高度| <= 1
     */
    public static class ReturnData{
        int height;
        boolean isBalance;

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

    public boolean isBalanceBinaryTree(Node root){
        return process2(root).isBalance;
    }

    private ReturnData process2(Node root) {
        if (root == null){
            return new ReturnData(0,true);
        }
        ReturnData leftData = process2(root.left);
        ReturnData rightData = process2(root.right);
        int height = Math.max(leftData.height,rightData.height)+1;
        boolean isBalance = leftData.isBalance && rightData.isBalance && Math.abs(leftData.height-rightData.height) < 2;
        return new ReturnData(height,isBalance);
    }


    public static void main(String[] args) {
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);
        Node node5 = new Node(5);
        Node node6 = new Node(6);
        Node node7 = new Node(7);
        node1.left = node2;
        node2.left = node4;
        node1.right = node3;
        node2.right = node5;
        node3.left = node6;
        node3.right = node7;
        TestNode testNode = new TestNode();
        System.out.println("=======递归===========");
        System.out.println("先序遍历");
        testNode.preOrder(node1);
        System.out.println("中序遍历");
        testNode.order(node1);
        System.out.println("后序遍历");
        testNode.lastOrder(node1);
        System.out.println("=======非递归===========");
        System.out.println("先序遍历");
        testNode.preOrderUnRecur(node1);
        System.out.println("中序遍历");
        testNode.orderUnRecur(node1);
        System.out.println("后序遍历");
        testNode.lastOrderUnRecur(node1);
        System.out.println("宽度遍历:");
        System.out.println(testNode.width(node1));
        System.out.println("判断是否是搜索二叉树");
        System.out.println(testNode.isBinarySearchTree(node1));
        System.out.println("判断是否是完全二叉树");
        System.out.println(testNode.isCompleteBinaryTree(node1));
        System.out.println("判断是否是满二叉树");
        System.out.println(testNode.isFullBinaryTree(node1));
        System.out.println("判断是否是平衡二叉树");
        System.out.println(testNode.isBalanceBinaryTree(node1));

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值