二叉树_题目笔记

最低公共祖先

简单逻辑版

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;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

写代码的信哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值