二叉树题目思路

思路

  1. 先求出当前二叉树的左树和右树的相关信息
  2. 对左树和右树的信息做处理,返回当前树的信息

题目

二叉树的完全性检验

题目:给定一个二叉树的 root ,确定它是否是一个 完全二叉树 。在一个 完全二叉树 中,除了最后一个关卡外,所有关卡都是完全被填满的,并且最后一个关卡中的所有节点都是尽可能靠左的。它可以包含 1 到 2h 节点之间的最后一级 h 。

解法一:

思路:

  1. 左树是满二叉树,右树是完全二叉树,且高度相同,则是完全二叉树
  2. 右树是满二叉树,左树是完全二叉树或者满二叉树,且高度比右二叉树加1,则是完全二叉树
public class TreeNode{
    int val;
    TreeNode left;
    TreeNode right;
    public TreeNode(int val) {
            this.val = val;
    }
}

public class Info{
    public boolean isFull;
    public boolean isCBT;
    public int height;
    
    public Info(boolean full, boolean cbt, int h) {
    	isFull = full;
    	isCBT = cbt;
    	height = h;
    }
}

public boolean isCompleteTree2(TreeNode root){
    if(root == null){
        return true;
    }
    return process(root).isCBT;
}

public Info process(TreeNode x){
    if(x == null){
        return new Info(true,true,0);
    }
    Info leftInfo = process(x.left);
    Info rightInfo = process(x.right);
    int height = Math.max(leftInfo.height,rightInfo.height)+1;
    boolean isFull = leftInfo.isFull && rightInfo.isFull && leftInfo.height = rightInfo.height;
    boolean isCBT = false;
    if(isFull){
        isCBT = true;
    } else {
        if(leftInfo.isCBT && rightInfo.isCBT){
            //1.左树是完全二叉树,右树是满树,且左树高度比右树高度+1
            if(leftInfo.isCBT && rightInfo.isFull && leftInfo.height == rightInfo.height + 1){
                isCBT = true;
            }
            //2.左树是满树,右树是满树,且左树高度比右树高度+1
            if(leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height + 1){
                isCBT = true;
            }
            //3.左树是满树,右树是完全二叉树,且左树高度和右树高度相等
            if(leftInfo.isFull && rightInfo.isCBT && leftInfo.height == rightInfo.height){
                isCBT = true;
            }
        }
    }
    return new Info(isFull,isCBT,height);
}

解法二:

思路:

  1. 做层序遍历,如果当前二叉树中节点只有一个右节点,或者只有左节点后,剩余的节点还有叶子节点,则说明是非完全二叉树
  2. 如果当前节点没有左节点,或者没有右节点,则说明当前节点后面都没有节点,设立一个参数,noNode=true
  3. 如果noNode=true,则说明后序节点只要任意一个有子节点,则说明非完全二叉树,返回false
public boolean isCompleteTree1(TreeNode root){
    if(root == null){
        return true;
    }
    
    Queue<TreeNode> queue = new LinkedList<>();
    TreeNode cur = root;
    queue.add(root);
    boolean noNode = false;
    while(!queue.isEmpty()){
        cur = queue.poll();
        if(cur.left == null && cur.right != null){
            return false;
        }
        if(noNode && (cur.left != null && cur.right != null)){
            return false;
        }
        if(cur.left != null){
            queue.add(cur.left);
        }
        if(cur.right != null){
            queue.add(cur.right);
        }
        if(cur.left == null || cur.right == null){
            noNode = true;
        }
    }
    return true;
}

public TreeNode generateRandomBST(int maxHeight,int maxValue){
    return generate(1,maxHeight,maxValue);
}

public TreeNode generate(int h,int maxHeight,int maxValue){
    if(h > maxHeight || Math.random() < 0.5){
        return null;
    }
    TreeNode node = new TreeNode((int)(Math.random()*maxValue));
    node.left = generate(h + 1,maxHeight,maxValue);
    node.right = generate(h + 1,maxHeight,maxValue);
    return node;
}

public static void main(String[] args){
    int testTimes = 1000;
    int maxH = 5;
    int maxV = 100;
    for (int i = 0; i < testTimes; i++) {
        TreeNode test = generateRandomBST(5,100);
        if(isCompleteTree1(testNode)!=isCompleteTree2(testNode)){
        	System.out.println("失败");
        }
    }
    System.out.println("成功");
}

判断是否是搜索二叉树

题目:给定一个二叉树,判断它是否是二叉查询树。

  1. 左节点及以下节点的值比它小;

  2. 右节点及以下节点的值比它大。当然,前提是子节点都存在的情况。

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

解法一:

思路:

1. 左树是搜索二叉树,右树是搜索二叉树
1. 左树的最大值小于val,右树的最小值大于val,则当前树是搜索二叉树
1. 因此,需要收集树的max,min,isBST
public class Info{
    public int max;
    public int min;
    public boolean isBST;
    
    public Info(int max,int min,boolean isBST){
        this.max = max;
        this.min = min;
        this.isBST = isBST;
    }
}

public boolean isBST2(Node head){
    if(head == null){
        return true;
    }
    
}

public Info process2(Node head){
    if(head == null){
        return new Info(Integer.MIN_VALUE,Integer.MAX_VALUE,true);
    }
    Info leftInfo = process2(head.left);
    Info rightInfo = process2(head.right);
    int max = Math.max(Math.max(leftInfo.max,rightInfo.max),head.value);
    int min = Math.min(Math.min(leftInfo.min, rightInfo.min), head.value);
    boolean isBST = true;
    if(!leftInfo.isBST || rightInfo.isBST){
        isBST = false;
    }
    if (leftInfo.max > head.value || rightInfo.min < head.value) {
        isBST = false;
    }
    return new Info(max,min,isBST);
}

解法二:

思路:

  1. 中序遍历访问每一个节点,并将该节点保存到list中,然后判断整个list是否是升序的
public boolean isBST1(Node head){
    if(head == null){
        reuturn true;
    }
    List<Node> list = new ArrayList<>();
    inOrder(head,list);
    for(int i= 0;i < list.size();i++){
        if(list.get(i) > list.get(i+1)){
            return false;
        }
    }
    return true;
}

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

判断是否是平衡二叉树

题目:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

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

解法一:

思路:

  1. 左树的高度和右树的高度差不超过1,且左树是平衡二叉树,右树是平衡二叉树
public boolean isBalanced1(Node head){
    if(head == null){
        return true;
    }
    return process1(head).isBal;
}

public class Info{
    public int height;
    public boolean isBal;
    
    public Info(int h,boolean isBal){
        this.height = h;
        this.isBal = isBal;
    }
}

public Info process1(Node head){
    if(head == null){
        return new Info(0,true);
    }
    Info leftInfo = process(head.left);
    Info rightInfo = process(head.right);
    int height = Math.max(leftInfo.height,rightInfo.height) + 1;
    boolean isBal = true;
    if(!leftInfo.isBal || !rightInfo.isBal){
        isBal = false;
    }
    if(Math.abs(leftInfo.height - rightInfo.height) > 1){
        isBal = false;
    }
    return new Info(height,isBal);
}

解法二:

  1. 返回当前节点的左树高度和右树高度,判断左树高度和右树是否大于1,大于,isBal=false
public boolean isBalanced2(Node head){
    if(head == null){
        return true;
    }
    boolean[] isBal = new boolean[1];
    isBal[0] = true;
    process2(head,isBal);
    return isBal[0];
}

public int process2(Node head,boolean[] isBal){
    if(head == null){
        return 0;
    }
    if(isBal[0] == false){
        return 0;
    }
    int leftHeight = process2(head.left,isBal);
    int rightHeight = process2(head.right,isBal);
    int h = Math.max(leftHight,rightHeight)+1;
    if(Math.abs(leftHeight - rightHeight) > 1){
        isBal[0] = false;
    }
    return h;
}

判断是否是满二叉树

题目:一个高度为h,并且含有2^h - 1个节点的二叉树称为满二叉树,下文称呼满二叉树为FBT。

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

解法一:

思路:

  1. 左树是满二叉树,右树是满二叉树,且左树高度等于右树高度,则当前树是满二叉树
public boolean isFull2(Node head){
    if(head == null){
        return true;
    }
    return process2(head).isFull;
}

public class Info2{
    public boolean isFull;
    public int height;
    
    public Info2(boolean isFull, int height){
        this.isFull = isFull;
        this.height = height;
    }
}

public Info2 process2(Node head){
    if(head == null){
        return new Info2(true,0);
    }
    Info2 leftInfo = process2(head.left);
    Info2 rightInfo = process2(head.right);
    int h = Math.max(leftInfo.height,rightInfo.height)+1;
    boolean isFull = true;
    if(!leftInfo.isFull || !rightInfo.isFull || leftInfo.height != rightInfo.height){
        isFull = false;
    }
    return new Info2(isFull,h);
}

解法二:

思路:

  1. 满二叉树满足$n=2^h-1$这个公式,因此,只需要知道当前树的结点个数n和高度h
public boolean isFull1(Node head){
    if(head == null){
        return true;
    }
    Info1 i = process1(head);
    return 2<<i.h == i.c+1;
    // (int)(Math.pow(2,i.h) -1) == i.c;
}

public class Info1{
    public int h;
    public int c;
    public Info1(int h ,int c){
        this.h = h;
        this.c = c;
    }
}

public Info1 process1(Node head){
    if(head == null){
        return new Info(0,0);
    }
    Info1 leftInfo = process1(head.left);
    Info2 rightInfo = process1(head.right);
    int h = Math.max(leftInfo.h,rightInfo.h) + 1;
    int c = leftInfo.c + rightInfo.c + 1;
    return new Info1(h,c);
}