树的搜索:递归与迭代找堂兄弟节点 | Java 刷题打卡

简介: 树的搜索:递归与迭代找堂兄弟节点 | Java 刷题打卡

网络异常,图片无法展示
|


题目描述



这是 LeetCode 上的 993. 二叉树的堂兄弟节点


Tag : 「树的搜索」、「BFS」、「DFS」


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

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


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


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


示例 1:


网络异常,图片无法展示
|


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


示例 2:


网络异常,图片无法展示
|


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


示例 3:


网络异常,图片无法展示
|


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


提示:


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


DFS



显然,我们希望得到某个节点的「父节点」&「所在深度」,不难设计出如下「DFS 函数签名」:


/**
 * 查找 t 的「父节点值」&「所在深度」
 * @param root 当前搜索到的节点
 * @param fa root 的父节点
 * @param depth 当前深度
 * @param t 搜索目标值
 * @return [fa.val, depth]
 */
int[] dfs(TreeNode root, TreeNode fa, int depth, int t);
复制代码


之后按照遍历的逻辑处理即可。


需要注意的时,我们需要区分出「搜索不到」和「搜索对象为 root(没有 fa 父节点)」两种情况。


我们约定使用 -11 代指没有找到目标值 tt,使用 00 代表找到了目标值 tt,但其不存在父节点。


代码:


class Solution {
    public boolean isCousins(TreeNode root, int x, int y) {
        int[] xi = dfs(root, null, 0, x);
        int[] yi = dfs(root, null, 0, y);
        return xi[1] == yi[1] && xi[0] != yi[0];
    }
    int[] dfs(TreeNode root, TreeNode fa, int depth, int t) {
        if (root == null) return new int[]{-1, -1}; // 使用 -1 代表为搜索不到 t
        if (root.val == t) {
            return new int[]{fa != null ? fa.val : 1, depth}; // 使用 1 代表搜索值 t 为 root
        }
        int[] l = dfs(root.left, root, depth + 1, t);
        if (l[0] != -1) return l;
        return dfs(root.right, root, depth + 1, t);
    }
}
复制代码


  • 时间复杂度:O(n)O(n)
  • 空间复杂度:忽略递归开销为 O(1)O(1),否则为 O(n)O(n)


BFS



能使用 DFS,自然也能使用 BFS,两者大同小异。


代码:


class Solution {
    public boolean isCousins(TreeNode root, int x, int y) {
        int[] xi = bfs(root, x);
        int[] yi = bfs(root, y);
        return xi[1] == yi[1] && xi[0] != yi[0];
    }
    int[] bfs(TreeNode root, int t) {
        Deque<Object[]> d = new ArrayDeque<>(); // 存储值为 [cur, fa, depth]
        d.addLast(new Object[]{root, null, 0});
        while (!d.isEmpty()) {
            int size = d.size();
            while (size-- > 0) {
                Object[] poll = d.pollFirst();
                TreeNode cur = (TreeNode)poll[0], fa = (TreeNode)poll[1];
                int depth = (Integer)poll[2];
                if (cur.val == t) return new int[]{fa != null ? fa.val : 0, depth};
                if (cur.left != null) d.addLast(new Object[]{cur.left, cur, depth + 1});
                if (cur.right != null) d.addLast(new Object[]{cur.right, cur, depth + 1});
            }
        }
        return new int[]{-1, -1};
    }
}
复制代码


  • 时间复杂度:O(n)O(n)
  • 空间复杂度:O(n)O(n)


最后



这是我们「刷穿 LeetCode」系列文章的第 No.993 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先将所有不带锁的题目刷完。


在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。


为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:github.com/SharingSour…


在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

相关文章
|
5天前
|
Java
java中递归实例
java中递归实例
17 0
|
5天前
|
Java C语言
详解java方法与递归
详解java方法与递归
10 3
|
15天前
|
自然语言处理 Java 编译器
【Java探索之旅】方法重载 递归
【Java探索之旅】方法重载 递归
10 0
|
15天前
|
Java 索引
JAVA刷题之数组的总结和思路分享
JAVA刷题之数组的总结和思路分享
|
15天前
|
Java
JAVA刷题之字符串的一些个人思路
JAVA刷题之字符串的一些个人思路
|
15天前
|
算法 Java
Java刷题有感
Java刷题有感
|
19天前
|
SQL Java 关系型数据库
java 递归返回树形组织结构(附带树形菜单的搜索)
java 递归返回树形组织结构(附带树形菜单的搜索)
16 0
|
19天前
|
存储 人工智能 Java
Java 构建树型结构
Java 构建树型结构
|
1天前
|
Java
Java中的多线程编程:基础知识与实践
【5月更文挑战第13天】在计算机科学中,多线程是一种使得程序可以同时执行多个任务的技术。在Java语言中,多线程的实现主要依赖于java.lang.Thread类和java.lang.Runnable接口。本文将深入探讨Java中的多线程编程,包括其基本概念、实现方法以及一些常见的问题和解决方案。
|
1天前
|
安全 算法 Java
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第13天】 在Java开发中,并发编程是一个复杂且重要的领域。它不仅关系到程序的线程安全性,也直接影响到系统的性能表现。本文将探讨Java并发编程的核心概念,包括线程同步机制、锁优化技术以及如何平衡线程安全和性能。通过分析具体案例,我们将提供实用的编程技巧和最佳实践,帮助开发者在确保线程安全的同时,提升应用性能。
10 1