二叉树题目套路

二叉树

平衡二叉树进阶

题目:给定一棵二叉树的头节点head,判断该树是否是平衡二叉树

  1. 根据标准想可能性,这一步是自己根据题意分析的。
    给定一棵二叉树的头节点head,判断该树是否是平衡二叉树。
    如果这棵树为平衡二叉树,那么它的子树也必为平衡二叉树
    判断子树的情况需要两个参数,一个是子树深度size,一个是子树是否平衡

  2. 根据支持可能心需要什么信息 收集信息 所有需要的信息做一个类型一次返回

  3. 先默认左右子树都能返回节点类型的信息
  4. 收集信息+决策过程
  5. 写了哪些信息需要返回,然后再加上自己这个当前节点向上返回,遇到base case跳出
public class IsBalancedTree {

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

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

    public static boolean isBalance(Node head) {
        boolean[] res = new boolean[1];
        res[0] = true;
        getHeight(head, 1, res);
        return res[0];
    }
    /*
    1.根据标准想可能性,这一步是自己根据题意分析的。
    给定一棵二叉树的头节点head,判断该树是否是平衡二叉树。
    如果这棵树为平衡二叉树,那么它的子树也必为平衡二叉树
    判断子树的情况需要两个参数,一个是子树深度size,一个是子树是否平衡
    */
    /*
    2.根据支持可能心需要什么信息 收集信息 所有需要的信息做一个类型一次返回 
    */
    public static class ReturnType {
        public int level;
        public boolean isB;

        public ReturnType(int l, boolean is) {
            level = l;
            isB = is;
        }
    }

    // process(head, 1)
    public static boolean m(Node head){
        return process(head, 1).isB;
    /*
    3.先默认左右子树都能返回节点类型的信息
    */
    public static ReturnType process(Node head, int level) {
        if (head == null) {//base case。空树认为是平衡二叉树
            return new ReturnType(level, true);
        }
        ReturnType leftSubTreeInfo = process(head.left, level + 1);
        /*
        4.收集信息
        */
        if(!leftSubTreeInfo.isB) {//左树不平衡 返回false 现在level没有意义
            return new ReturnType(level, false);
        }
        ReturnType rightSubTreeInfo = process(head.right, level + 1);
        if(!rightSubTreeInfo.isB) {//右树不平衡 返回false
            return new ReturnType(level, false);
        }

        //前面两步都没返回,说明左右子树都平衡
        //现在看左右子树高度差是否超过1
        if (Math.abs(rightSubTreeInfo.level - leftSubTreeInfo.level) > 1) {
            return new ReturnType(level, false);
        }
        /*
        4.收集信息+决策过程
        */
        //树的深度取左右子树深的那一个        
        return new ReturnType(Math.max(leftSubTreeInfo.level, rightSubTreeInfo.level), true);
        /*
        5.写了哪些信息需要返回,然后再加上自己这个当前节点向上返回
        */
    }

    public static int getHeight(Node head, int level, boolean[] res) {
        if (head == null) {
            return level;
        }
        int lH = getHeight(head.left, level + 1, res);
        if (!res[0]) {
            return level;
        }
        int rH = getHeight(head.right, level + 1, res);
        if (!res[0]) {
            return level;
        }
        if (Math.abs(lH - rH) > 1) {
            res[0] = false;
        }
        return Math.max(lH, rH);
    }

    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(isBalance(head));

    }

}

二叉搜索树进阶

题目:给定一棵二叉树的头节点head,已知所有节点的值都不一样,求最大的搜索二叉子树的节点数量。

/*
1.根据标准想可能性
可能性1 最大搜索二叉树在左树上
可能性2 最大搜索二叉树在右树上
可能性3 最大搜索二叉树是根节点所在的整棵树
2.支持可能性所需要的信息
左树上最大搜索二叉树的size
右树上最大搜索二叉树的size
子树上最大搜索二叉树的头部,不是树的头部
这棵树的最大值和最小值
    其实只需要左树的最大值和右树的最小值,但是每个递归过程都是一样的
    所以我们搜集信息的时候要全部收集,然后让上级决策
3.默认左右子树都能返回如上的信息
4.拿到收集的信息,如何组合出可能性1、2、3
5.写了哪些信息需要返回,加上当前节点的信息,组合好,向上返回,遇到base case跳出
*/
public class BiggestSubBSTInTree {

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

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

    public static Node biggestSubBST(Node head) {
        int[] record = new int[3]; // 0->size, 1->min, 2->max
        return posOrder(head, record);
    }

    public static class ReturnType{
        public int size;//左树上最大搜索二叉树的size。不是左树的size
        public Node head;//左树上最大搜索二叉树的头部,不是左树的头部
        public int min;//整个范围内的最小最大值
        public int max;

        public ReturnType(int a, Node b,int c,int d) {
            this.size =a;
            this.head = b;
            this.min = c;
            this.max = d;
        }
    }

    public static ReturnType process(Node head) {
        if(head == null) {
            return new ReturnType(0,null,Integer.MAX_VALUE, Integer.MIN_VALUE);
        }
        Node left = head.left;
        ReturnType leftSubTressInfo = process(left);
        Node right = head.right;
        ReturnType rightSubTressInfo = process(right);

        int includeItSelf = 0;
        if(leftSubTressInfo.head == left 
                &&rightSubTressInfo.head == right
                && head.value > leftSubTressInfo.max
                && head.value < rightSubTressInfo.min
                ) {
            includeItSelf = leftSubTressInfo.size + 1 + rightSubTressInfo.size;
        }
        int p1 = leftSubTressInfo.size;
        int p2 = rightSubTressInfo.size;
        int maxSize = Math.max(Math.max(p1, p2), includeItSelf);
        //左右子树中选长度大的那一个
        Node maxHead = p1 > p2 ? leftSubTressInfo.head : rightSubTressInfo.head;
        if(maxSize == includeItSelf) {//第三种情况,左右都是搜索二叉树,加上自己也是搜索二叉树
            maxHead = head;
        }

        return new ReturnType(maxSize,
                maxHead, 
                Math.min(Math.min(leftSubTressInfo.min,rightSubTressInfo.min),head.value),
                Math.max(Math.max(leftSubTressInfo.max,rightSubTressInfo.max),head.value)); 
    }




    public static Node posOrder(Node head, int[] record) {
        if (head == null) {
            record[0] = 0;
            record[1] = Integer.MAX_VALUE;
            record[2] = Integer.MIN_VALUE;
            return null;
        }
        int value = head.value;
        Node left = head.left;
        Node right = head.right;
        Node lBST = posOrder(left, record);
        int lSize = record[0];
        int lMin = record[1];
        int lMax = record[2];
        Node rBST = posOrder(right, record);
        int rSize = record[0];
        int rMin = record[1];
        int rMax = record[2];
        record[1] = Math.min(rMin, Math.min(lMin, value)); // lmin, value, rmin -> min 
        record[2] =  Math.max(lMax, Math.max(rMax, value)); // lmax, value, rmax -> max
        if (left == lBST && right == rBST && lMax < value && value < rMin) {
            record[0] = lSize + rSize + 1;
            return head;
        }
        record[0] = Math.max(lSize, rSize);
        return lSize > rSize ? lBST : rBST;
    }

    // for test -- 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(6);
        head.left = new Node(1);
        head.left.left = new Node(0);
        head.left.right = new Node(3);
        head.right = new Node(12);
        head.right.left = new Node(10);
        head.right.left.left = new Node(4);
        head.right.left.left.left = new Node(2);
        head.right.left.left.right = new Node(5);
        head.right.left.right = new Node(14);
        head.right.left.right.left = new Node(11);
        head.right.left.right.right = new Node(15);
        head.right.right = new Node(13);
        head.right.right.left = new Node(20);
        head.right.right.right = new Node(16);

        printTree(head);
        Node bst = biggestSubBST(head);
        printTree(bst);

    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值