993.二叉树的堂兄弟节点(简单)|Java 刷题打卡

237 阅读2分钟

本文正在参加「Java主题月 - Java 刷题打卡」,详情查看 活动链接

一、题目描述

在二叉树中,根节点位于深度0处,每个深度为k的节点的子节点位于深度k+1处。

如果二叉树的两个节点深度相同,但 **父节点不同 **,则它们是一对堂兄弟节点。

我们给出了具有唯一值的二叉树的根节点root,以及树中两个不同节点的值xy

只有与值xy对应的节点是堂兄弟节点时,才返回true 。否则,返回false

示例 1:

输入:root = [1,2,3,4], x = 4, y = 3 输出:false

示例 2:

img

输入:root = [1,2,3,null,4,null,5], x = 5, y = 4 输出:true

示例 3:

img

输入:root = [1,2,3,null,4], x = 2, y = 3 输出:false

提示:

  • 二叉树的节点数介于2100之间。
  • 每个节点的值都是唯一的、范围为1100的整数。

二、分析

两个节点是堂兄弟节点的条件:两个节点在同一层但是它们的父节点不同,所以只要遍历这棵树,遍历过程中维护每个节点的父节点和深度,比较这两个节点的深度和父节点即可。所以问题转化为遍历一棵二叉树,遍历二叉树的方法很多,前序遍历,中序遍历,后序遍历,这些属于DFS(深度优先遍历),当然也可以用BFS(广度优先遍历),其实就是层级遍历

先看一下二叉树前序遍历递归方式,这段代码应该要不假思索地写出来。我们在这个基础上改造就可以了

public void preOrderTraverse(TreeNode root) {
        if (root != null) {
            System.out.print(root.val + "->");
            preOrderTraverse(root.left);
            preOrderTraverse(root.right);
        }
    }

要点就是在preOrderTraverse方法中增加两个参数parentdepth,用来表示当前遍历节点的父节点和当前节点的深度,preOrderTraverse每次调用时都会遍历root.left或者root.right,遍历的是下一层所以父节点是root,深度depth直接加1就OK了

class Solution {

  int x;
  int y;
  int xParent;
  int xDepth;
  int yParent;
  int yDepth;

  public boolean isCousins(TreeNode root, int x, int y) {
    this.x = x;
    this.y = y;
    preOrderTraverse(root, root, 1);
    return xParent != yParent && xDepth == yDepth;
  }

  public void preOrderTraverse(TreeNode root, TreeNode parent, int depth) {
    if (root != null) {
      if (root.val == x) {
        this.xParent = parent.val;
        this.xDepth = depth;
      }
      if (root.val == y) {
        this.yParent = parent.val;
        this.yDepth = depth;
      }

//      System.out.print(root.val + "(" + parent.val + depth + ")" + "->");
      preOrderTraverse(root.left, root, depth + 1);
      preOrderTraverse(root.right, root, depth + 1);
    }
  }
}

三、总结

时间复杂度为O(n),n就是这棵树的节点个数,遍历一棵树就是遍历这n个节点。上述代码还有优化的地方,在遍历过程中,应该是找到了就推出循环,而不是要把整棵树遍历完。