最低公共祖先
简单逻辑版
public static Node lCA(Node head, Node o1, Node o2) {
//o1,o2 是头为head的这棵树的节点
//返回最低公共祖先
HashMap<Node, Node> fatherMap = new HashMap<>();
//头节点的父亲设置为自己
fatherMap.put(head, head);
process(head, fatherMap);
HashSet<Node> set1 = new HashSet<>();
set1.add(o1);
Node cur = o1;
//只有头节点是父节点等于自己, 设置这个条件一直向上循环
while (cur != fatherMap.get(cur)) {
set1.add(cur);
cur = fatherMap.get(cur);
}
set1.add(head); //把树的头节点放进去. 至此就把从o1开始向上的所有节点存在了里面
//如此再从o2进行一次, 向上的过程判断,当前这个在set1中有没有,有的话就找到了那个最低公共祖先
Node cur2 = o2;
while (cur2 != fatherMap.get(cur2)) {
cur2 = fatherMap.get(cur2);
if (set1.contains(cur2)) {
return cur2;
}
}
return head;
}
public static void process(Node head, HashMap<Node, Node> fatherMap) {
if (head == null) {
return;
}
//向上回溯节点的父节点
fatherMap.put(head.left, head);
fatherMap.put(head.right, head);
process(head.left, fatherMap);
process(head.right, fatherMap);
}
简洁代码版
分两种情况
- O1是O2的最低公共祖先,或者O2是O1的最低公共祖先。那么就直接返回。
- 彼此不互为公共祖先,就需要向上汇聚找到。
public static Node lowestAncestor(Node head, Node o1, Node o2) {
if (head == null || head == o1 || head == o2) {
return head;
}
Node left = lowestAncestor(head.left, o1, o2);
Node right = lowestAncestor(head.right, o1, o2);
if (left != null && right != null) {
return head;
}
return left != null ? left : right;
}
后继节点
定义:后继节点是中序遍历的下一个节点。
节点给了父节点的情况下,能不能优化时间复杂度为O(k),k为两节点的距离节点数。
设X 的后继节点是 Y
为了实现优化,分情况讨论:
- X有右树的情况,X的右孩子就是后继节点
- X没有右树,向上走的同时判断我是不是我父亲的左孩子,如果是,这个祖先就是后继节点
- X是整棵树的最后一个节点,后继为null
代码
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;// node和parent一起向上
}
return parent;
}
}
public static Node getLeftMost(Node node) {
if (node == null) {
return node;
}
while (node.left != null) {
node = node.left;
}
return node;
}
二叉树的序列化和反序列化
序列化的思想就是将树的节点转换成符号,解码也很容易理解。
public static String serialByPre(Node head) {
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.offer(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;
}