如何判断一棵二叉树是否是搜索二叉树?
搜索二叉树的定义:一个节点,其左数的节点都比它小,右数的节点都比它大(一般没有重复的值)
思路:判断是否是搜索二叉树,可以采用中序遍历(左头右),看是否升序。
代码:递归/存入链表,判断是否升序
如何判断一棵二叉树是否是完全二叉树?
思路:1)任一节点,有右无左孩子,返回false 2)在1)成立的情况下下,如果遇到了第一个左右两个孩子不双全,后续节点是叶子节点
如何判断是否是满二叉树?
满二叉树(除了叶子节点外,所有节点都有两个子节点)的节点数N和最大深度L满足,N=2^L-1
如何判断是否是平衡二叉树?
平衡二叉树:任意节点的子树的高度差都小于1
判断平衡二叉树要知道 : 1)左子树是否是平衡二叉树 2)右子树是否是平衡二叉树 3)|左高 - 右高| 小于等于1
左子树返回的信息:是否是平衡二叉树、高度;右子树返回的信息:是否是平衡二叉树、高度
public static boolean isBalance(Node head){
return process(head).isBalanced;
}
public static class ReturnType{
public boolean isBalanced;
public int height;
public ReturnType(boolean isB, int hei){
isBalanced = isB;
height = hei;
}
}
public static ReturnType process(Node x){
if(x == null){//base
return new ReturnType(true, 0);
}
ReturnType leftData = process(x.left);
ReturnType rightData = process(x.right);
int height = Math.max(leftData.height, rightData.height) + 1;
boolean isBalanced = leftData.isBalanced && rightData.isBalanced && Math.abs(leftData.height - rightData.height) < 2;
return new ReturnType(isBalanced, height);
}
这是一类套路题,便于后续做树形DP
求解一个二叉树问题时,列可能性:假设在可以和左树要信息,和右树要信息的情况下
搜索二叉树:左树要是搜索二叉树,右树要是搜索二叉树 左max小于x,右min大于x
左数右树信息:是否是搜索二叉树,max,min(左树要求和右树要求求全集)
public static class ReturnData{
public boolean isBST;
public int min;
public int max;
public ReturnData(boolean is, int mi, inr ma){
isBST = is;
max = ma;
min = mi;
}
}
public static ReturnData process(Node x){
if(x == null){
return null;
}
ReturnData leftData = process(x.left);
ReturnData rightData = process(x.right);
int min = x.value;
int max = x.value;
if(leftData != null){
min = Math.min(min, leftData.min);
max = Math.max(max, leftData.max);
}
if(rightData != null){
min = Math.min(min, rightData.min);
max = Math.max(max, rightData.max);
}
boolean isBST = true;
if(leftData != null && left.isBST || leftDAta.max >= x.value){
isBst = false;
}
if(rightData != null && right.isBST || rightData.min <= x.value){
isBst = false;
}
return new ReturnData(isBst,min,max);
}
是否是满二叉树
public static boolean isF(Node x){
if(head == null){
return true;
}
Info data = process(head);
return data.nodes == (1 << data.height -1);
}
public static class Info{
public int height;
public int nodes;
public Info(int h ,int n){
height = h;
nodes = n;
}
}
public static Info process(Node x){
if(x == null){
return new Info(0,0);
}
Info leftData = process(x.left);
Info rightData = process(x.right);
int height = Math.max(leftData.height,right.height)+1;
int nodes = leftData.nodes + rightData.nodes + 1;
return new Info(height, nodes);
}
最低公共祖先
//o1 o2 一定属于head为头的树
//返回o1 和 o2 公共祖先
public static Node lca(Node head ,Node o1, Node o2) {
HashMap<Node,Node> fatherMap = new HashMap<>();
fatherMap.put(head, head);
process(head,fatherMap);
HashSet<Node> set1 = new HashSet<>();
ste.add(o1);
Node cur = o1;
while(cur != fatherMap.get(cur)){
set1.add(cur);
cur = fatherMap.get(cur);
}
set1.add.head;
while o2 set1
}
public static void process(Node head, HashMap<Node, Node> fatherMap) {
if(head == null){
return;
}
fatherMap.put(head.left, head);
fatherMap.put(head.right,right);
process(head.left,fatherMap);
process(head.right,fatherMap)
}
后续节点
中序遍历中一个节点的下一个节点(线索二叉树)
分情况:x有右树,后继节点为右树上的最左节点;x无右树,往上走,看是不是父节点的左孩子
public static Node getSuccessorNode(Node node){
if(node == null){
return node;
}
if(node.right != null){
return getLeftMost(node.right);
}else{//无右子树
Node parent = node.parent;
while(parent != null && parent.left != node){//当前节点是其父节点的右孩子
node = parent;
parent = node.parent;
}
return parent;
}
}
public static Node getLeftMost(Node node){
if (node == null){
return node;
}
while( node.left != null){
node = node.left;
}
return node;
}
二叉树序列和反序列化(剑指offer)
//先序方式
public static String seriaByPre(Node node){
if(head == null){
return "#_";
}
String res = head.value + "_";
res += serialByPre(head.left);
res += serialByPre(head.right);
return res;
}
//反序列化
public static Node reconByPreString(String preStr){
String[] values = preStr.split("_");
Queue<String> queue = new LinkedList<String>();
for(int i = 0; i != values.length; i++){
queue.add(values[i]);
}
return reconPreOrder(queue);
}
public static Node reconPreOrder(Queue<String> queue){
String value = queue.poll();
if(value.equals("#"){
return null;
}
Node head = new Node(Integer.valueOf(value));
head.left = reconPreOrder(queue);
head.right = reconPreOrder(queue);
return head;
}
折纸问题
//递归过程
//i是节点的层数,N一共的层数,down == true凹 down ==false 凸
public static void printProcess(int i, int N, boolean down){
if(i > N){
return ;
}
printProcess(i+1,N,true);
System.out.println(down ? "凹" :"凸");
printProcess(i+1,N,false);
}