二叉树 — 返回最大二叉搜索树的头结点

这道题与返回最大二叉搜索树的大小类似,都是收集并判断左右子树的信息。

  1. 递归的方式收集每个节点的信息,并拼装成info对象供上层调用。
  2. max用来判断左子树最大值是否小于当前节点,min用来判断右子树最小值是否大于当前节点,maxSubBSTSize 最大二叉搜索子树大小,maxSubBSTHead 最大二叉搜索子树的头结点。
  3. 一共三种情况,最大二叉搜索子树在左子树,最大二叉搜索子树在右子树和整棵树都为最大二叉搜索树。
  4. 如果整棵树都是二叉搜索树,则需要左子树的最大值 < 当前节点 < 右子树的最大值,并且左右子树的最大二叉搜索树的head节点,就是我当前节点的left、right节点。

递归方法

public static class Info {
        int max;
        int min;
        Node maxSubBSTHead;
        int maxSubBSTSize;

        public Info(int max, int min, Node maxSubBSTHead, int maxSubBSTSize) {
            this.max = max;
            this.min = min;
            this.maxSubBSTHead = maxSubBSTHead;
            this.maxSubBSTSize = maxSubBSTSize;
        }
    }
 public static Node maxSubBSTHead1(Node head) {
        if (head == null) {
            return head;
        }
        return process(head).maxSubBSTHead;
    }

    public static Info process(Node head) {
        if (head == null) {
            return null;
        }

        Info leftInfo = process(head.left);
        Info rightInfo = process(head.right);

        int max = head.val;
        int min = head.val;
        Node maxSubBSTHead = null;
        int maxSubBSTSize = 0;
        if (leftInfo != null) {
            max = Math.max(leftInfo.max, max);
            min = Math.min(leftInfo.min, min);
            maxSubBSTHead = leftInfo.maxSubBSTHead;
            maxSubBSTSize = leftInfo.maxSubBSTSize;
        }

        if (rightInfo != null) {
            max = Math.max(rightInfo.max, max);
            min = Math.min(rightInfo.min, min);
            //如果左右子树都不为null,用maxSubSBTSize变量判断哪个子树的头结点更大。
            if (rightInfo.maxSubBSTSize > maxSubBSTSize) {
                maxSubBSTHead = rightInfo.maxSubBSTHead;
                maxSubBSTSize = rightInfo.maxSubBSTSize;
            }
        }
        //第一次进来时,先等于当前节点
        //如果 左数的最大二叉树头结点 是我当前节点的 left节点
        //并且 右树的最大二叉树头节点 是我当前节点的 right 节点 则说明我的左右子树都是搜索二叉树
        //那么 最大的搜索二叉树头节点,就等于我当前节点。
        if ((leftInfo == null ? true : (leftInfo.maxSubBSTHead == head.left && leftInfo.max < head.val))
                && (rightInfo == null ? true : (rightInfo.maxSubBSTHead == head.right && rightInfo.min > head.val))) {

            maxSubBSTHead = head;
            maxSubBSTSize = (leftInfo == null ? 0 : leftInfo.maxSubBSTSize) + (rightInfo == null ? 0 : rightInfo.maxSubBSTSize) + 1;
        }
        return new Info(max, min, maxSubBSTHead, maxSubBSTSize);
    }

暴力方式
中序遍历(左 -> 头 -> 右)的方式,遍历整棵二叉树,放到集合中,并遍历集合,如果整个集合元素都是由小到大的顺序,说明整棵树都是搜索二叉树,直接返回。
否则,递归遍历,找到最大的搜索二叉树。

  public static Node maxSubBSTHead2(Node head) {
        if (head == null) {
            return head;
        }

        if (getMaxSize(head) != 0) {
            return head;
        }

        Node left = maxSubBSTHead2(head.left);
        Node right = maxSubBSTHead2(head.right);

        return getMaxSize(left) >= getMaxSize(right) ? left : right;
    }

    public static int getMaxSize(Node head) {
        if (head == null) {
            return 0;
        }
        List<Node> list = new ArrayList<>();
        in(head, list);
        for (int i = 1; i < list.size(); i++) {
            if (list.get(i).val <= list.get(i - 1).val) {
                return 0;
            }
        }
        return list.size();
    }

	public static void in(Node head, List<Node> list) {
	        if (head == null) {
	            return;
	        }
	        in(head.left, list);
	        list.add(head);
	        in(head.right, list);
	    }

你可能感兴趣的:(leetCode,算法,java,算法,二叉树)