题目摘要
题目链接
题目截图
题目模板
class Solution {
public boolean isCousins(TreeNode root, int x, int y) {
}
}
解题思路
首先阅读题目,这里我直接把题目中的关键信息做了加粗处理
在二叉树中,根节点位于深度 0 处,每个深度为 k 的节点的子节点位于深度 k+1 处。如果二叉树的两个节点深度相同,但父节点不同 ,则它们是一对_堂兄弟节点_。我们给出了具有唯一值的二叉树的根节点 root ,以及树中两个不同节点的值 x 和 y 。只有与值 x 和 y 对应的节点是堂兄弟节点时,才返回 true 。否则,返回 false。
第一眼看到这个题目,Easy难度的题,感觉比较简单,直接用最笨的方法来写就好了,先把关键信息摘要出来:
- 题目给的是一棵二叉树
- 符合条件的两个节点要求深度相同但父节点不同
- 模板中方法返回值为一个布尔值,仅需要判断两个节点是否为符合条件的节点
树的遍历
既然是要在树中搜索两个节点,那树的遍历肯定是逃不开
对于树的遍历一般有三种:先序遍历、中序遍历、后续遍历。对于这道题我的主观感觉上三种遍历形式没有什么不同,所以就随机采取了中序遍历这种方式,毕竟代码写起来建店,下面是代码:
class Solution {
public boolean isCousins(TreeNode root, int x, int y) {
traversingTree(root);
return false;
}
private void traversingTree(TreeNode root) {
if (Objects.isNull(root)) {
return;
}
System.out.println(root.val);
traversingTree(root.left);
traversingTree(root.right);
}
}
值的传递
结果的两个节点需要符合的条件:
- 深度相同
- 父节点不同
既然要判断这两个值,那我们在遍历树的过程中,肯定要先能取到这两个值以及这两个节点。这里也没有什么高深莫测的方法,直接进行简单透传即可,下面是代码:
class Solution {
public boolean isCousins(TreeNode root, int x, int y) {
traversingTree(root, x, y, 0, -1);
return false;
}
private void traversingTree(TreeNode root, int x, int y, int layer, int parent) {
if (Objects.isNull(root)) {
return;
}
System.out.println(root.val);
traversingTree(root.left, x, y, layer + 1, root.val);
traversingTree(root.right, x, y, layer + 1, root.val);
}
}
结果记录
由于要记录两个节点的深度、父节点两个信息,所以这里我直接新建了一个对象来保存信息:
class Solution {
public boolean isCousins(TreeNode root, int x, int y) {
traversingTree(root, x, y, 0, -1, new Result());
return false;
}
private void traversingTree(TreeNode root, int x, int y, int layer, int parent, Result res) {
if (Objects.isNull(root)) {
return;
}
System.out.println(root.val);
traversingTree(root.left, x, y, layer + 1, root.val, res);
traversingTree(root.right, x, y, layer + 1, root.val, res);
}
private class Result {
int layer = -1;
int parent = -1;
}
}
这里留个疑问点,为什么不直接用两个int变量透传下去?
条件判断
万事俱备只欠东风,不多说,直接给出最终的代码:
class Solution {
public boolean isCousins(TreeNode root, int x, int y) {
return traversingTree(root, x, y, 0, -1, new Result());
}
private boolean traversingTree(TreeNode root, int x, int y, int layer, int parent, Result res) {
if (Objects.isNull(root)) {
return false;
}
if (x == root.val || y == root.val) {
if (res.layer == -1 || res.parent == -1) {
res.layer = layer;
res.parent = parent;
} else if (res.parent != parent && res.layer == layer) {
return true;
}
}
return traversingTree(root.left, x, y, layer + 1, root.val, res)
|| traversingTree(root.right, x, y, layer + 1, root.val, res);
}
private class Result {
int layer = -1;
int parent = -1;
}
}
这里主要有几个改动点:
- 遍历方法返回值改成了boolean,方便遍历过程中做判断,也方便直接调用返回结果
- 如果根节点为null,则直接返回false,防止出现NPE以及遍历中断的情况
- 因为题目中没有给出x和y的左右关系,所以直接使用x == root.val || y == root.val的条件来判断是否符合条件,也就忽略了x和y的先后关系
- 当res的两个值为-1时,认为是初始化状态,当第一次命中节点时,先赋值,第二次命中节点时再判断