这是悦乐书的第374次更新,第401篇原创

01 看题和准备

今天介绍的是LeetCode算法题中Easy级别的第235题(顺位题号是993)。在二叉树中,根节点在深度0处,并且每个深度为k的节点的子节点,他们深度为k + 1

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

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

当且仅当对应于值x和y的节点是堂兄弟时,才返回true。例如:

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

      1
/ \
2 3
/
4

输出:false



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

      1
/ \
2 3
\ \
4 5

输出:true



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

      1
/ \
2 3
\
4

输出:false

注意

  • 树中的节点数将介于2和100之间。

  • 每个节点都有一个从1到100的唯一整数值。

02 第一种解法

题目的意思是xy在同一层,但是他们的父级节点不一样,也就是xy属于堂兄弟的关系。

使用BFS(广度优先)的算法,通过迭代的方式借助Stack来实现,使用了一个额外的方法,分别求出xy的层级和他们的父级节点,用一个长度为2的数组返回,如果xy的层级相同且父级结点不同,就返回true

/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/ public boolean isCousins(TreeNode root, int x, int y) {
int[] arr = getTreeDepth(root, x);
int[] arr2 = getTreeDepth(root, y);
if (arr.length < 1 || arr2.length < 1) {
return false;
}
return arr[0] != arr2[0] && arr[1] == arr2[1];
} public int[] getTreeDepth(TreeNode root, int num) {
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
int depth = 0;
while (!stack.isEmpty()) {
Stack<TreeNode> stack2 = new Stack<TreeNode>();
while (!stack.isEmpty()) {
TreeNode tem = stack.pop();
if (tem.left != null) {
// 当前节点的左子节点值等于要找的数
if (tem.left.val == num) {
return new int[] {tem.val, depth+1};
}
stack2.push(tem.left);
}
if (tem.right != null) {
// 当前节点的右子节点值等于要找的数
if (tem.right.val == num) {
return new int[] {tem.val, depth+1};
}
stack2.push(tem.right);
}
}
stack = stack2;
depth++;
}
return new int[] {};
}

03 第二种解法

针对第一种解法,我们也可以将判断的方法融合在一起,依旧是借助

/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/ public boolean isCousins2(TreeNode root, int x, int y) {
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
while (!stack.isEmpty()) {
Stack<TreeNode> stack2 = new Stack<TreeNode>();
boolean xExist = false, yExist = false;
while (!stack.isEmpty()) {
TreeNode tem = stack.pop();
if (tem.val == x) {
xExist = true;
}
if (tem.val == y) {
yExist = true;
}
// x和y不能有同一个父节点
if (tem.left != null && tem.right != null) {
if (tem.left.val == x && tem.right.val == y) {
return false;
}
if (tem.left.val == y && tem.right.val == x) {
return false;
}
}
if (tem.left != null) {
stack2.push(tem.left);
}
if (tem.right != null) {
stack2.push(tem.right);
}
}
stack = stack2;
if (xExist && yExist) {
return true;
}
}
return false;
}

04 第三种解法

和第二种解法思路一样,只是将栈换成了队列

/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/ public boolean isCousins3(TreeNode root, int x, int y) {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
boolean xExist = false, yExist = false;
for (int i=0; i<size; i++) {
TreeNode tem = queue.poll();
if (tem.val == x) {
xExist = true;
}
if (tem.val == y) {
yExist = true;
}
// x和y不能有同一个父节点
if (tem.left != null && tem.right != null) {
if (tem.left.val == x && tem.right.val == y) {
return false;
}
if (tem.left.val == y && tem.right.val == x) {
return false;
}
}
if (tem.left != null) {
queue.offer(tem.left);
}
if (tem.right != null) {
queue.offer(tem.right);
}
}
if (xExist && yExist) {
return true;
}
}
return false;
}

05 第四种解法

借助递归,一个递归方法求深度,一个递归方法找父节点,最后判断深度是否相同且父节点不同。

/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/ public boolean isCousins4(TreeNode root, int x, int y) {
return getDepth(root, x, 0) == getDepth(root, y, 0) &&
findParent(root, x) != findParent(root, y);
} public int getDepth(TreeNode root, int num, int depth){
if (root == null) {
return 0;
}
if (root.val == num) {
return depth;
}
int left = getDepth(root.left, num, depth+1);
int right = getDepth(root.right, num, depth+1);
return Math.max(left, right);
} public int findParent(TreeNode root, int num) {
if (root == null) {
return 0;
}
if (root.left != null && root.left.val == num) {
return root.val;
}
if (root.right != null && root.right.val == num) {
return root.val;
}
int left = findParent(root.left, num);
int right = findParent(root.right, num);
return Math.max(left, right);
}

06 第五种解法

我们也可以只是用一次递归方法,借助全局变量来解。

/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/ private int depthX;
private int depthY;
private TreeNode parentX;
private TreeNode parentY; public boolean isCousins5(TreeNode root, int x, int y) {
helper(root, x, y, 0, null);
return depthX == depthY && parentX != parentY;
} public void helper(TreeNode root, int x, int y, int depth, TreeNode parent) {
if (root == null) {
return ;
}
if (root.val == x) {
depthX = depth;
parentX = parent;
} else if (root.val == y) {
depthY = depth;
parentY = parent;
}
helper(root.left, x, y, depth+1, root);
helper(root.right, x, y, depth+1, root);
}

07 第六种解法

我们还可以将第五种解法中找父节点的变量换成int类型,因为节点值唯一,可以直接使用节点值参与判断。

/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/ private int depthX;
private int depthY;
private int parentX;
private int parentY; public boolean isCousins6(TreeNode root, int x, int y) {
helper(root, x, y, 0, 0);
return depthX == depthY && parentX != parentY;
} public void helper(TreeNode root, int x, int y, int depth, int parent) {
if (root == null) {
return ;
}
if (root.val == x) {
depthX = depth;
parentX = parent;
} else if (root.val == y) {
depthY = depth;
parentY = parent;
}
helper(root.left, x, y, depth+1, root.val);
helper(root.right, x, y, depth+1, root.val);
}

08 小结

算法专题目前已连续日更超过七个月,算法题文章241+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!

LeetCode.993-二叉树中的堂兄弟(Cousins in Binary Tree)的更多相关文章

  1. [Swift]LeetCode124. 二叉树中的最大路径和 | Binary Tree Maximum Path Sum

    Given a non-empty binary tree, find the maximum path sum. For this problem, a path is defined as any ...

  2. 二叉树中的最大路径和 · Binary Tree Maximum Path Sum

    [抄题]: 给出一棵二叉树,寻找一条路径使其路径和最大,路径可以在任一节点中开始和结束(路径和为两个节点之间所在路径上的节点权值之和) [思维问题]: 不会写分合法 [一句话思路]: 用两次分治:ro ...

  3. LeetCode 103. 二叉树的锯齿形层次遍历(Binary Tree Zigzag Level Order Traversal)

    103. 二叉树的锯齿形层次遍历 103. Binary Tree Zigzag Level Order Traversal 题目描述 给定一个二叉树,返回其节点值的锯齿形层次遍历.(即先从左往右,再 ...

  4. LeetCode 104. 二叉树的最大深度(Maximum Depth of Binary Tree)

    104. 二叉树的最大深度 104. Maximum Depth of Binary Tree 题目描述 给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数. 说 ...

  5. LeetCode 145. 二叉树的后序遍历(Binary Tree Postorder Traversal)

    题目描述 给定一个二叉树,返回它的 后序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [3,2,1] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 解题思路 后 ...

  6. LeetCode 114. 二叉树展开为链表(Flatten Binary Tree to Linked List)

    题目描述 给定一个二叉树,原地将它展开为链表. 例如,给定二叉树 1 / \ 2 5 / \ \ 3 4 6 将其展开为: 1 \ 2 \ 3 \ 4 \ 5 \ 6 解题思路 二叉树转化为链表的基本 ...

  7. 【LeetCode】993. Cousins in Binary Tree 解题报告(C++ & python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS BFS 日期 题目地址:https://le ...

  8. LeetCode 993. Cousins in Binary Tree(判断结点是否为Cousin)

    993. Cousins in Binary Tree In a binary tree, the root node is at depth 0, and children of each dept ...

  9. 【Leetcode_easy】993. Cousins in Binary Tree

    problem 993. Cousins in Binary Tree 参考 1. Leetcode_easy_993. Cousins in Binary Tree; 完

随机推荐

  1. PMBOK :美国的项目管理知识体系

    PMBOK 是Project Management Body Of Knowledge的缩写, 指项目管理知识体系的意思,具体是美国项目管理协会(PMI)对项目管理所需的知识.技能和工具进行的概括性描 ...

  2. Ubuntu 安装matlab2013b

    下载软件包: 链接:http://pan.baidu.com/s/1bHoFHc 密码:lugc 还要注意软件的解压的问题: 链接:http://pan.baidu.com/s/1geBEQyf 密码 ...

  3. vue中使用echarts(vue+vue-cli+axios+jsonp+echarts)

    一.安装echarts: cnpm i echarts -D 二.在vue-cli的main.js文件中引用echarts: import charts from 'echarts' Vue.prot ...

  4. SpringMVC页面中文乱码

    刚开始学习使用SpringMVC,完成配置之后开始编辑页面源码,添加了几个中文字符(index.jsp) <html> <body> <h2>hello world ...

  5. dede cms 怎样调用年月日

    一: 首页:([field:pubdate function='strftime("%m-%d",@me)'/])==(5-15)([field:pubdate function= ...

  6. 通过喝水清晰简单了解I/O五大模型

    一般单次I/O请求会分为两个阶段,每个阶段对于I/O的处理方式是不同的 I/O会经历一个等待资源的阶段 阻塞,指的是在数据不可用时,I/O请求会一直阻塞,直到数据返回 数据不可用时,立即返回,直到被通 ...

  7. HTML的<form>表单标签

    表单 HTML 表单用于搜集不同类型的用户输入. ㈠Form标签 ⑴form标签简介 在HTML中,如果创建一个表单,就把各种表单标签放在<form></form>标签内部.我 ...

  8. 红黑树(RB-tree)比AVL树的优势在哪?

    1. 如果插入一个node引起了树的不平衡,AVL和RB-Tree都是最多只需要2次旋转操作,即两者都是O(1):但是在删除node引起树的不平衡时,最坏情况下,AVL需要维护从被删node到root ...

  9. Linux下kafka集群的搭建

    上一篇日志已经搭建好了zookeeper集群,详细请查看:http://www.cnblogs.com/lianliang/p/6533670.html,接下来继续搭建kafka的集群 1.首先下载k ...

  10. ruby_类的调用及require的使用

    在文件arrayTest_1中,定义class Liuyang内容如下:(通过require File.expand_path('../arrayTest_2',__FILE__) 来包含其他文件的文 ...