读书笔记之《程序员代码面试指南(二叉树问题)》

二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。

代码 Github 地址

判断二叉树是不是平衡二叉树

输入一棵二叉树的根节点,判断该树是不是平衡的二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。

先比较左边,再比较右边;

左子树也先比较左边再比较右边。

  public boolean isBalance(Node head){
        boolean res=true;
        getHeight(head,1,res);
        return res;
    }

    public int getHeight(Node head , int level ,boolean res){
        if(head==null){
            return level;
        }

        int lH=getHeight(head.left,level+1,res);
        if(!res){
            return level;
        }

        int rH=getHeight(head.right,level+1,res);
        if(!res){
            return level;
        }

        if(Math.abs(lH-rH)>1){
            res=false;
        }
        return Math.max(lH,rH);
    }

根据后序数组重建搜索二叉树

给定一个整型数组arr,已知其中没有重复值,判断arr是否可能是节点值类型为整型的搜索二叉树后序遍历的结果。

数组最后一个值,肯定是根节点的值

小于根节点的为左子树,大于根节点的为左子树

对应2,1,3小于4

6,5,7大于4

 public static void main(String [] args){
        int [] arr={2,1,3,6,5,7,4};
        System.out.println(isPostArray(arr));
    }

    public static boolean isPostArray(int [] arr){
        if(arr==null || arr.length==0){
            return false;
        }
        return isPost(arr,0,arr.length-1);
    }


    public static boolean isPost(int [] arr, int start ,int end){
        if(start==end){
            return true;
        }
        int less=-1;
        int more=end;

        for(int i=start;i<end;i++){
            if(arr[i]<arr[end]){
            less=i;
        }else {
            more=more==end ? i : more;
            }
        }

        if(less==-1||more==end){
            return isPost(arr,start,end-1);
        }
        if(less!=more-1){
            return false;
        }
      
        return isPost(arr,start,less)&&isPost(arr,more,end-1);
    }

二叉树的序列化和反序列化

package BinaryTree;

import java.util.LinkedList;
import java.util.Queue;

/**
 * Created by zdmein on 2017/9/7.
               12
           /      \
         3        null
     /    \
  null    null
 先序遍历:12!3!#!#!#!
 */
public class NodeSerial {
    /**
     * 定义Node
     */
    public class Node{
        public int value;
        public Node left;
        public Node right;

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

    /**
     * 先序遍历
     */
    public String serialByPre(Node head){
        if(head==null){
            return "#!";
        }

        String res=head.value+"!";
        res+=serialByPre(head.left);
        res+=serialByPre(head.right);
        return res;
    }

    /**
     * 先序遍历反序列化
     */
    public Node reconByPreString(String preStr){
        String [] values=preStr.split("!");
        Queue<String> queue=new LinkedList<String>();
        for(int i=0;i<values.length;i++){
            queue.offer(values[i]);
        }
        return reconPreOrder(queue);
    }

    /**
     * Queue
     add        增加一个元索                     如果队列已满,则抛出一个IIIegaISlabEepeplian异常
     remove     移除并返回队列头部的元素         如果队列为空,则抛出一个NoSuchElementException异常
     element    返回队列头部的元素               如果队列为空,则抛出一个NoSuchElementException异常
     offer      添加一个元素并返回true           如果队列已满,则返回false
     poll       移除并返问队列头部的元素         如果队列为空,则返回null
     peek       返回队列头部的元素               如果队列为空,则返回null
     put        添加一个元素                     如果队列满,则阻塞
     take       移除并返回队列头部的元素         如果队列为空,则阻塞
     */

    public Node reconPreOrder(Queue<String> queue){
        String value = queue.poll();
        if(value.equals("#")){
            return null;
        }

        Node head=new Node(Integer.valueOf(value));
        Node left=reconPreOrder(queue);
        Node right=reconPreOrder(queue);
        return head;
    }
    
}

找到二叉树中的最大搜索二叉子树

题目:给定一棵二叉树的头节点head, 已知其中所有节点的值都不一样,
找到含有节点最多的搜索二叉子树,并返回这颗子树的头节点。

package BinaryTree;

/**
 * Created by zdmein on 2017/9/8.
 * 找到二叉树中的最大搜索二叉子树
 题目:给定一棵二叉树的头节点head, 已知其中所有节点的值都不一样,
 找到含有节点最多的搜索二叉子树,并返回这颗子树的头节点。
                             6
                          /    \
                       1       12
                     /\       /    \
                   0   3     10       13
                            /  \      /  \
                           4    14    2   9
                          /\     /\
                         2  5    1  6
 二叉搜索树:
        10
       /  \
     4     14
    / \    / \
   2  5   1   6

 要求:
 如果节点数为N,要求时间复杂度为O(N) ,额外空间复杂度为O(h),h为二叉树的高度。
 解:
 以节点node为头的树中,最大的搜索二叉子树只可能来自一下两种情况。
 1.如果来自node左子树上的最大搜索二叉子树是以node.left为头的;来自node右子树的最大搜索二叉树是以
 node.right为头的;node左子树上的最大搜索二叉子树的最大值小于node.value;
 node右子树的最大搜索二叉子树的最小值大于node.value,那么以节点node为头的整棵树都是搜索二叉树。
 2如果不满足第一中情况,说明节点node为头的整颗树不能连成搜索二叉树。这种情况下,以node为头的树上的最大搜索二叉子树来自node的左子树上的最大搜索二叉子树和来自右子树上的最大搜索二叉子树之间,
 节点较多的那个。
 过程如下:
 1,整个过程是二叉树的后序遍历。(左右根)
 2,遍历到当前节点记为cur时,先遍历cur的左子树收集4个信息,分别是左子树上最大搜索二叉子树的头节点(IBST) ,节点数(ISize),最小值(IMin),最大值(IMax).
 再遍历cur的右子树收集4个信息,分别是右子树上最大搜索二叉子树的头节点(RBST) ,节点数(RSize),最小值(RMin),最大值(RMax).
 3, 根据步骤2收集的信息,判断是否满足第一种情况,如果满足第一种情况就返回cur,如果满足第二种情况,就返回IBST和RBST中较大的一个。
 4,可以使用全局变量的方式实现步骤2中收集节点数,最大和最小的情况。
 */
public class biggestSubBST1 {
    public class Node{
        public int value;
        public Node left;
        public Node right;

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

    public Node biggestSubBST(Node head){
        int [] record =new int[3];
        return posOrder(head , record);
    }

    public 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(value,lMin);
        record[2]=Math.max(value,rMax);
        if(left==lBST&&right==rBST&&lMax<value&&rMin>value){
            record[0]=lSize+rSize+1;
            return head;
        }

        record[0]=Math.max(lSize,rSize);
        return lSize>rSize?head.left:head.right;
    }
}

找到二叉树中符合搜索二叉树条件的最大拓扑结构

posted @ 2018-01-29 18:52  daminzhou  阅读(373)  评论(0编辑  收藏  举报