什么是二叉树?
二叉树是一种常见的数据结构。其中每个节点最多有两个子节点,分别为左子节点和右子节点。如果一个节点没有子节点,则称该节点为叶节点。每个节点都有一个值,用来储存任意类型的数据,这个值对应着节点的唯一标识。二叉树有很多种变形,有些会要求节点左子节点的值一定要小于右子节点的值,而有些则不限制节点值大小。
在二叉树中,任意两个节点之间都可以称为“父子节点关系”。如果一个节点 A 具有左子节点 B,则我们说节点 A 是节点 B 的父节点,节点 B 是节点 A 的子节点。同理,如果一个节点 C 具有右子节点 D,则我们说节点 C 是节点 D 的父节点,节点 D 是节点 C 的子节点。
如何找到一个节点?
在二叉树中找到一个节点,有很多方法。其中最常见的方法就是遍历整个树,直到找到需要的节点。具体来说,我们有以下三种遍历方式:
前序遍历:从根节点开始,先遍历左子树,再遍历右子树。
中序遍历:从根节点开始,先遍历左子树,然后访问根节点,最后遍历右子树。
后序遍历: 从根节点开始,先遍历左子树,再遍历右子树,最后访问根节点。
为了找到一个节点,我们需要在遍历时做出一些判断。如果当前节点的值等于我们要找的节点值,我们就可以停止遍历,因为已经找到了该节点。
如何找到符合条件的节点?
现在我们需要找到一个节点,使得从该节点到叶节点的所有路径都是相同颜色的。在这里,我们用二叉树来表示这些路径,其中每个节点的颜色就代表着该节点到根节点的路径颜色。因此,我们需要找到一个节点,使得所有以该节点为根节点的子树中,路径颜色都相同。
这样的节点并不一定存在。如果存在,该节点一定是某个路径上的某个节点,它的子树中所有的路径颜色都和该路径上的颜色相同。因此,我们可以从根节点开始遍历,逐个判断每个节点是否符合要求。具体来说,我们可以按任意一种遍历方式,递归地搜索每个子树:
public TreeNode findNode(TreeNode node, int color) {
if (node == null) {
return null;
}
if (node.left == null && node.right == null) {
return node;
}
if (getColor(node.left, color) == getColor(node.right, color)) {
return node;
}
TreeNode left = findNode(node.left, getColor(node.left, color));
TreeNode right = findNode(node.right, getColor(node.right, color));
return left == null ? right : left;
}
private int getColor(TreeNode node, int defaultColor) {
return node == null ? defaultColor : node.val;
}
在代码中,我们用 findNode 方法来递归搜索每个子树, getColor 方法用来获取当前节点的颜色。如果当前节点的左子树和右子树的颜色相同,那么就说明该节点符合要求,直接返回;否则,我们递归地在其左子树和右子树中寻找符合要求的节点。如果左子树中不存在这样的节点,则在右子树中寻找,反之亦然。
如何测试代码?
为了测试我们的代码,我们需要先自己创建一棵二叉树。在这个例子中,我们可以先手动建立如下的二叉树:
10
/ \
5 20
/ \ / \
4 6 15 25
/ \
22 30
上面的二叉树共有 7 个叶节点,每个叶节点代表一条路径。为了使得所有到叶节点的路径颜色都相同,我们可以把上面二叉树整体染色。在这个例子中,我们可以把所有偶数节点染成红色,所有奇数节点染成蓝色。这样,我们就把所有到叶节点的路径颜色都固定下来了。
最后,我们可以用以下代码来测试我们的代码:
public class Main {
public static void main(String[] args) {
TreeNode node = buildTree();
TreeNode result = findNode(node, node.val);
System.out.println(result.val);
}
private static TreeNode buildTree() {
TreeNode root = new TreeNode(10);
root.left = new TreeNode(5);
root.right = new TreeNode(20);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(6);
root.right.left = new TreeNode(15);
root.right.right = new TreeNode(25);
root.right.right.left = new TreeNode(22);
root.right.right.right = new TreeNode(30);
return root;
}
private static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) {
this.val = val;
}
}
}
运行上述代码,我们可以得到以下输出结果:
20
其中,20 就是我们找到的符合要求的节点。