二叉树-距离是K的二叉树节点(hard)

2024-06-16 22:04
文章标签 二叉树 距离 节点 hard

本文主要是介绍二叉树-距离是K的二叉树节点(hard),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、问题描述

二、解题思路

1.总体思路(DFS+BFS结合)

2.下面举具体例子来对思路进行解释

(1)返回值在一侧的情况

(2)返回值在两侧的情况

三、代码实现

四、刷题链接


一、问题描述

二、解题思路

1.总体思路(DFS+BFS结合)

        使用深度遍历DFS算法获得目标结点所在路径(不包含目标结点和根节点),保存在ArrayList中,同时我们可以根据下标可以知道祖先结点距离目标结点的距离(dis),根据这个差值(k-dis),我们就可以使用广度优先遍历(层序遍历BFS算法)来求祖先节点的第(k-dis)层的子孙结点

2.下面举具体例子来对思路进行解释

返回值结点可能在根节点单侧或双侧的情况

(1)返回值在一侧的情况

再来看一个例子target=1,k=2时:

(2)返回值在两侧的情况

画红色框框的是需要比较的几个关键结点。

三、代码实现

import java.util.*;/** public class TreeNode {*   int val = 0;*   TreeNode left = null;*   TreeNode right = null;*   public TreeNode(int val) {*     this.val = val;*   }* }*/public class Solution {int depth=0;TreeNode resNode=new TreeNode(-1);HashSet<Integer> findSet=new HashSet<>();ArrayList<Integer> arr = new ArrayList<>();ArrayList<TreeNode> nodes=new ArrayList<>();/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param root TreeNode类 * @param target int整型 * @param k int整型 * @return int整型一维数组*/public ArrayList<Integer> distanceKnodes (TreeNode root, int target, int k) {boolean isSide=false;boolean isleft=false;if(k==0){arr.add(target);return arr;}if(root.val==target){//直接执行bfs即可bfs(root.left,k-1);bfs(root.right,k-1);return arr;}// 先检查是否在左侧dfs(root.left,target,1);if(depth!=0){isleft=true;}else{dfs(root.right,target,1);}if(depth<k){isSide=false;}else{isSide=true;}if(isSide){//结果都在根节点一侧//遍历target子孙结点bfs(resNode,k);//如果是根节点if(k==nodes.size()+1){arr.add(root.val);}for(int i=0;i<nodes.size();i++){if(k==i+1){//如果祖先结点路径上存在距离为k的节点,也要返回arr.add(nodes.get(i).val);}//祖先结点的孩子结点存在距离为k的结点返回(注意避开目标结点所在路径)if(nodes.get(i).left!=null&&!findSet.contains(nodes.get(i).left.val)){bfs(nodes.get(i).left,k-i-1-1);}if(nodes.get(i).right!=null&&!findSet.contains(nodes.get(i).right.val)){bfs(nodes.get(i).right,k-i-1-1);}}}else{//结果分散在根节点两侧int diff=k-depth;if(isleft){//遍历右侧深度为diff-1的结点bfs(root.right,diff-1);}else{//遍历右侧深度为diff-1的结点bfs(root.left,diff-1);}//遍历target子孙结点bfs(resNode,k);//遍历祖先节点for(int i=0;i<nodes.size();i++){if(nodes.get(i).left!=null&&!findSet.contains(nodes.get(i).left.val)){bfs(nodes.get(i).left,k-i-1-1);}if(nodes.get(i).right!=null&&!findSet.contains(nodes.get(i).right.val)){bfs(nodes.get(i).right,k-i-1-1);}}}return arr; }//遍历第depth层的结点public void bfs(TreeNode root,int depth){if(root==null){return;}int layernum=0;//深度是从0开始的Queue<TreeNode> nowqueue=new LinkedList<>();nowqueue.offer(root);int nowlayerNodenum=1;//当前层的剩余结点数量int nextlayerNodenum=0;//下一层的结点数量while(!nowqueue.isEmpty()){TreeNode nownode=nowqueue.poll();if(layernum==depth){arr.add(nownode.val);}nowlayerNodenum--;if(nownode.left!=null){nowqueue.offer(nownode.left);nextlayerNodenum++;}if(nownode.right!=null){nowqueue.offer(nownode.right);nextlayerNodenum++;}if(nowlayerNodenum==0){nowlayerNodenum=nextlayerNodenum;layernum++;//开启下一层的遍历操作nextlayerNodenum=0;if(layernum>depth){break;}}}}public boolean dfs(TreeNode root,int target,int nowdepth){if(root==null){return false;}if(root.val==target){depth=nowdepth;resNode=root;findSet.add(root.val);return true;}else{boolean leftbool=dfs(root.left,target,nowdepth+1);boolean rightbool=dfs(root.right,target,nowdepth+1);if(leftbool||rightbool){nodes.add(root);findSet.add(root.val);return true;}else{return false;}}}
}

四、刷题链接

距离是K的二叉树节点_牛客题霸_牛客网

这篇关于二叉树-距离是K的二叉树节点(hard)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1067669

相关文章

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

day-51 合并零之间的节点

思路 直接遍历链表即可,遇到val=0跳过,val非零则加在一起,最后返回即可 解题过程 返回链表可以有头结点,方便插入,返回head.next Code /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}*

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

leetcode105 从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。 注意: 你可以假设树中没有重复的元素。 例如,给出 前序遍历 preorder = [3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7] 返回如下的二叉树: 3/ \9 20/ \15 7   class Solution {public TreeNode buildTree(int[] pr

JS和jQuery获取节点的兄弟,父级,子级元素

原文转自http://blog.csdn.net/duanshuyong/article/details/7562423 先说一下JS的获取方法,其要比JQUERY的方法麻烦很多,后面以JQUERY的方法作对比。 JS的方法会比JQUERY麻烦很多,主要则是因为FF浏览器,FF浏览器会把你的换行也当最DOM元素。 <div id="test"><div></div><div></div

PHP实现二叉树遍历(非递归方式,栈模拟实现)

二叉树定义是这样的:一棵非空的二叉树由根结点及左、右子树这三个基本部分组成,根据节点的访问位置不同有三种遍历方式: ① NLR:前序遍历(PreorderTraversal亦称(先序遍历)) ——访问结点的操作发生在遍历其左右子树之前。 ② LNR:中序遍历(InorderTraversal) ——访问结点的操作发生在遍历其左右子树之中(间)。 ③ LRN:后序遍历(PostorderT

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

OpenStack离线Train版安装系列—3控制节点-Keystone认证服务组件

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版

OpenStack离线Train版安装系列—2计算节点-环境准备

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版

OpenStack离线Train版安装系列—1控制节点-环境准备

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版