目录
每日算法(一)——二叉树
判断二叉树是否为平衡二叉树
平衡二叉树
一个二叉树*每个节点 *的左右两个子树的高度差的绝对值不超过1。
思路: 利用递归收集左右子树的深度以及子树是否是平衡二叉树 实现 函数返回一个ReturnData类
class ReturnData{
// 是否平衡
boolean bal;
// 深度
int deep;
public ReturnData(boolean bal,int deep){
this.bal = bal;
this.deep = deep;
}
}
public boolean isBalanced(TreeNode root) {
if(root == null) return true;
return isB(root).bal;
}
public ReturnData isB(TreeNode root){
if(root == null)return new ReturnData(true,0);
ReturnData left = isB(root.left);
ReturnData right = isB(root.right);
int deeps = Math.max(left.deep,right.deep) + 1;
// 如果高度差大于1 或者 左/右子树不平衡
if(Math.abs(left.deep - right.deep) > 1 || !left.bal ||!right.bal) return new ReturnData(false,deeps);
else return new ReturnData(true,deeps);
}
二叉树中找到一个节点的后继节点
有父节点
思路: > 根据中序遍历是升序可知 后继为例: 1. 有右节点,则后继节点就是该右子树的最左节点 2. 没有右子树,则不断往上回溯找到 par.left = ch
public TreeNode successor(TreeNode node){
if( node == null){
return null;
}
// 情况1,有右子树,则后继节点就是该右子树的最左节点
if( node.right != null){
TreeNode tmp = node.right;
while(tmp.left != null)
tmp = tmp.left;
return tmp;
}else{
// 情况2 没有右子树,则不断往上回溯找到 par.left = ch
TreeNode par = node.parent;
TreeNode ch = node;
while(par != null && ch == par.right){
ch = par;
par = par.parent;
}
return par;
}
}
public TreeNode predecessor(TreeNode node){
// 和后继是反过来的
if( node == null){
return null;
}
// 情况1,有左子树,则后继节点就是该左子树的最右节点
if( node.left!= null){
TreeNode tmp = node.left;
while(tmp.right != null)
tmp = tmp.right;
return tmp;
}else{
// 情况2 没有左子树,则不断往上回溯找到 par.right = ch
TreeNode par = node.parent;
TreeNode ch = node;
while(par != null && ch == par.left){
ch = par;
par = par.parent;
}
return par;
}
}
无父节点
思路: 1. 情况1 p是最大节点 没有后继 返回null 2. 情况2 p有右子树 找右子树最左节点 3. 情况3 p没有右子树 快慢指针
public TreeNode successor(TreeNode root, TreeNode node) {
// 边界判断
if (node == null) return null;
// 情况1 p是最大节点 没有后继 返回null
if (getMaxNode(node) == node) return null;
// 情况2 p有右子树 找右子树最左节点
if (node.right != null) return getMinNode(node.right);
// 情况3 p没有右子树
TreeNode parent = root;
TreeNode temp = root;
while (parent != null) {
if (parent == node) {
break;
} else if (node.val < parent.val) {
temp = parent;
parent = parent.left;
} else {
parent = parent.right;
}
}
return temp;
}
public TreeNode getMaxNode(TreeNode node) {
if (node == null) return null;
while (node.right != null) {
node = node.right;
}
return node;
}
public TreeNode getMinNode(TreeNode node) {
if (node == null) return null;
while (node.left != null) {
node = node.left;
}
return node;
}
二叉树找到两个节点的最近公共祖先
思路: 利用递归 看是否能够找到两个节点 找到后就返回 如果左子树和右子树找到的节点都不为空 说明左/右子树都发现了2个节点中的一个 则2者节点往上走首先在遍历到的当前节点相遇 如果有一个为空 一个不为空 说明可能当前的node 是2者的最近公共祖先 或者是二者中的一个
public static Node findFather(Node head, Node o1, Node o2) {
if (head == null || head == o1 || head == o2) {
return head;
}
Node left = findFather(head.left, o1, o2);
Node right = findFather(head.right, o1, o2);
if (left != null && right != null) return head;
return left != null ? left : right;
}
二叉树结点间的最大距离
思路: 最大距离来自于
- 左/右子树的最大距离
- 经过当前节点的最远距离
于是用一个全局变量保存 左/右子树据结点的最大距离
public static int maxDistance(Node head) {
int[] record = new int[1];
return posOrder(head, record);
}
private static int posOrder(Node head, int[] record) {
if (head == null) {
record[0] = 0;
return 0;
}
int lMax = posOrder(head.left, record);
// 距离左子节点的最大距离
int maxfromLeft = record[0];
int rMax = posOrder(head.right, record);
// 距离右子节点的最大距离
int maxfromRight = record[0];
int curNodeMax = maxfromLeft + maxfromRight + 1;
record[0] = Math.max(maxfromLeft, maxfromRight) + 1;
return Math.max(Math.max(lMax, rMax), curNodeMax);
}