算法总结:左神class5—二叉树是否是平衡二叉树,搜索二叉树,平衡二叉树
二叉树实现堆,增删改查都是O(LOGN),没有扩容代价
一 判断一棵二叉树是否是平衡二叉树(AVL):任何一个节点的左右子树高度只差 <=1
大流程:以每个节点的树都是平衡的,则整棵树就是平衡的。
对于某个节点,需要收集信息:
1 左树是否平衡?否直接faulse;
2 是,同理判断右数是否平衡;
3 两子树都平衡,判断两子树的高度差 <=1?
(套路化操作:列出可能性之后,写代码非常简单)
【优化】树形BP:在二叉树上做动态规划---进阶班
二 判断是否是搜索二叉树(BST,Binary Search Tree)二叉排序树,二叉查找树:对于一棵树上任何一个节点的子树,左子树 < 节点 < 右子树 。通常不出现重复节点,如果有重复节点,可以把它们的值压缩在一 个节点的内部。
一个二叉树的中序遍历结果依次升序的,则为搜索二叉树(一般搜索二叉树不含重复节点)中序非递归遍历打印的时机来判断是否比上一个node大
红黑树、平衡搜索二叉树(AVL树)等,其实都是搜索二叉树的不同实现。
三 判断是否为完全二叉树CBT,Complete Binary Tree):
堆就是一个完全二叉树。不过堆使用数组位置对应出来的。完全二叉树是指除了最后一层之外,其他每一层的节点数都是满的。最后一层如果也满了,是一颗满二叉树,也是完全二叉树。最后一层如果不满,缺少的节点也全部的集中在右边,那也是一颗完全二叉树。
广度优先遍历 按层遍历
一个节点只有右孩子没有左孩子,则非完全二叉树,
一个节点有左没右或者两个都没有,后面的所有节点都是叶节点,则为完全二叉树
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class Code_07_IsBSTAndCBT {
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
//一.递归判断是否是平衡二叉树
public static class ReturnData {
public boolean isB;// 是否平衡
public int h;// 高度
public ReturnData(boolean isB, int h) {// 基本初始化
this.isB = isB;
this.h = h;
}
}
// 递归跑 主函数 后序遍历
public static Boolean isB(Node head) {
return process(head).isB;
}
public static ReturnData process(Node head) {
if (head == null) {
return new ReturnData(true, 0);// 空树高度为0的平衡树
}
ReturnData leftData = process(head.left);
if (!leftData.isB) {// 左不平衡直接faulse
return new ReturnData(false, 0);// 只要不平衡,高度值没用,随意随便写
}
ReturnData rightData = process(head.right);
if (!rightData.isB) {// 右不平衡
return new ReturnData(false, 0);
}
if (Math.abs(leftData.h - rightData.h) > 1) {// 判断两边高度
return new ReturnData(false, 0);
}
return new ReturnData(true, Math.max(leftData.h, rightData.h) + 1);
// 左树高度和右数高度大1的高度即为整棵树高度
}
//二.递归判断是否是二叉搜索树
int pre = Integer.MIN_VALUE;
public static Boolean isBST1(Node head) {
boolean res = true;
if (head == null) {
return res;
}
isBST1(head.left);
if (head.value > pre) {
pre = head.value;
} else {
res = false;
}
isBST1(head.right);
return res;
}
//非递归morris遍历
public static Boolean isBST2(Node head) {
int pre = Integer.MIN_VALUE;
boolean res = true;
if (head != null) {
Stack<Node> stack = new Stack<Node>();
while (!stack.isEmpty() || head != null) {
if (head != null) {
stack.push(head);
head = head.left;
} else {
head = stack.pop();
// 下面的if else 相当于
// System.out.print(head.value + "");
// 打印时机替换成比较时机,用一个变量记住上一次的值来判断是否为中序遍历升序
if (head.value > pre) {
pre = head.value;
} else {
res = false;
}
head = head.right;
}
}
}
return res;
System.out.printIn();
}
//三.判断是否是完全二叉树
public static boolean isCBT(Node head) {
if (head == null) {
return true;
}
//LinkedList是双端链表,可以实现队列结构
Queue<Node> queue = new LinkedList<Node>();
boolean leaf = false;
Node l = null;
Node r = null;
queue.offer(head);
while (!queue.isEmpty()) {
head = queue.poll();
l = head.left;
// 判断完全二叉树的两个标准:
// ①某个节点有右孩子没有左孩子,则不是完全二叉树
// ②满足①的条件下,某个节点没有右孩子有左孩子,
// 或者没有左右孩子时,后面遇到的所有节点必须是叶节点。
if ((leaf && (l != null || r != null))
||
(l == null && r != null)) {
return false;
}
if (l != null) {
queue.offer(l);// 宽度遍历先压左
}
if (r != null) {
queue.offer(r);// 再压右
}
if (l == null || r == null) {
leaf = true;
}
}
return true;
}
// 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(5);
head.left = new Node(3);
head.right = new Node(8);
head.left.left = new Node(2);
head.left.right = new Node(4);
head.right.left = new Node(6);
head.right.right = new Node(10);
head.left.left.left = new Node(1);
head.right.left.right = new Node(7);
head.right.right.left = new Node(9);
printTree(head);
System.out.println(isB(head)); //true
System.out.println(isBST1(head)); //true
System.out.println(isBST2(head)); //true
System.out.println(isCBT(head)); //false
}
}
public class IsBalanced2 {
public boolean IsBalanced_Solution(TreeNode root) {
return getDepth(root) != -1;
}
private int getDepth(TreeNode root) {
if (root == null)
return 0;
int leftDepth = getDepth(root.left);
if (leftDepth == -1) {
return -1;
}
int rightDepth = getDepth(root.right);
if (rightDepth == -1) {
return -1;
}
return Math.abs(leftDepth - rightDepth) > 1 ? -1 : Math.max(leftDepth, rightDepth) + 1;
}
}