二叉树-距离是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的二叉树节点_牛客题霸_牛客网

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/715056.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

对接钉钉Stream模式考勤打卡相关事件的指南

钉钉之前的accessToken是公司级别的&#xff0c;现在的accessToken是基于应用的&#xff0c;接口的权限也是基于应用的。所以第一步是在钉钉开放平台&#xff08;https://open-dev.dingtalk.com/&#xff09;创建一个应用。 创建好应用之后&#xff0c;因为我们后续还需要调用钉…

---异常---

我们在运行程序时总遇到各种与报错&#xff0c;数组越界&#xff0c;空指针的引用&#xff0c;这些在java中都称为异常 对于不同的错误都具有一个与他对应的异常类来秒描述 这是对于数组越界这个类里有的方法&#xff0c;这些是描述异常的 在java中有一个完整的描述异常的类的…

C/C++ Adaline自适应线性神经网络算法详解及源码

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

MySQL之高级特性(四)

高级特性 查询缓存 什么情况下查询缓存能发挥作用 并不是什么情况下查询缓存都会提高系统性能的。缓存和失效都会带来额外的消耗&#xff0c;所以只有当缓存带来的资源节约大于本身的资源消耗时才会给系统带来性能提升。这跟具体的服务器压力模型有关。理论上&#xff0c;可…

实现贪吃蛇小游戏【简单版】

1. 贪吃蛇游戏设计与分析 1.1 地图 我们最终的贪吃蛇大纲要是这个样子&#xff0c;那我们的地图如何布置呢&#xff1f; 这里不得不讲⼀下控制台窗口的⼀些知识&#xff0c;如果想在控制台的窗口中指定位置输出信息&#xff0c;我们得知道该位置的坐标&#xff0c;所以首先介…

微信小程序毕业设计-博客系统项目开发实战(附源码+论文)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计…

龙迅LT9611UXC 2 PORT MIPIDSI/CSI转HDMI 2.1,支持音频IIS/SPDIF输入,支持标准4K60HZ输出

龙迅LT9611UXC描述&#xff1a; LT9611UXC是一个高性能的MIPI DSI/CSI到HDMI2.0转换器。MIPI DSI/CSI输入具有可配置的单端口或双端口&#xff0c;1高速时钟通道和1~4高速数据通道&#xff0c;最大2Gbps/通道&#xff0c;可支持高达16Gbps的总带宽。LT9611UXC支持突发模式DSI视…

Uniapp实现页面滚动Tab吸顶,点击tab内容滚动到对应tab内容位置

思路&#xff1a;运用uniapp原生提供方法uni.createSelectorQuery()获取滚动对应节点的信息&#xff0c;即节点距离页面顶部的距离&#xff0c;再通过uniapp原生监听页面滚动事件onPageScroll&#xff0c;获取页面内容滚动的高度&#xff0c;二者相加即定位到对应节点的滚动距离…

java设计模式和面向对象编程思想

Java设计模式和面向对象编程思想是软件开发中的核心概念&#xff0c;对于构建可维护、可扩展的软件系统至关重要。下面是对这两个主题的知识点总结&#xff1a; 面向对象编程&#xff08;OOP&#xff09;思想 封装&#xff1a;将数据&#xff08;属性&#xff09;和操作这些数据…

如何选择合适的大模型框架:LangChain、LlamaIndex、Haystack 还是 Hugging Face

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学。 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 合集&#x…

详解 Spring Security:全面保护 Java 应用程序的安全框架

详解 Spring Security&#xff1a;全面保护 Java 应用程序的安全框架 Spring Security 是一个功能强大且高度可定制的框架&#xff0c;用于保护基于 Java 的应用程序。它为身份验证、授权、防止跨站点请求伪造 (CSRF) 等安全需求提供了解决方案。下面将更详细地介绍 Spring Se…

ComfyUI

文章目录 一、关于 ComfyUI特点快捷键QA你为什么做这个&#xff1f;这是给谁的&#xff1f; 二、安装1、Windows直接链接下载如何在另一个UI和ComfyUI之间共享模型&#xff1f; 2、Jupyter Notebook3、手动安装&#xff08;Windows、Linux&#xff09;AMD GPU&#xff08;仅Lin…

2024年黑龙江省特岗招聘公告出了!!!

2024年黑龙江省农村义务教育阶段学校特设岗位教师招聘822人公告 (1、网上报名 时间&#xff1a;6月17日9&#xff1a;00—6月22日17&#xff1a;00。 网址&#xff1a; https&#xff1a;//sfyz.hljea.org.cn&#xff1a;7006/tgjs 2、网上资格审查 资格审查时间&#xff1a;6月…

时间卷积网络与膨胀卷积:深入理解其原理与应用

TCN, Temporal Convolutional Networks 时间卷积网络与膨胀卷积&#xff1a;深入理解其原理与应用一、时间卷积网络&#xff08;TCN&#xff09;简介二、膨胀卷积的核心概念1. **膨胀卷积&#xff08;Dilated Convolution&#xff09;**2. **Kernel&#xff08;卷积核&#xff…

js 前端 Function.prototype.call.call(0[‘toString‘], *, 16)

这个函数将 数组转任意进制 Function.prototype.call.call(0[toString], *, 16)

计算机组成原理之定点运算器的组成

文章目录 定点运算器的组成逻辑运算ALU两级先行进位的ALU 总线单总线结构双总线结构三总线结构 定点运算器的组成 逻辑运算 总的来说&#xff0c;逻辑非运算就是按位取反&#xff1b;逻辑加运算就是按位取或运算&#xff1b;逻辑乘运算就是按位取和运算&#xff1b;逻辑异运算…

2-6 基于matlab2018B的语音信号降噪和盲源分离GUI界面

基于matlab2018B的语音信号降噪和盲源分离GUI界面&#xff0c;包括维纳滤波&#xff0c;小波降噪、高通、低通、带通滤波&#xff0c;及提出的滤波方法。每个功能均展示降噪前后声音效果并外放出来。程序已调通&#xff0c;可直接运行。 2-6 语音信号降噪 盲源分离 GUI界面 - 小…

UML相关2

内容 说明 用例编号 UC-1 用例名称 客户注册 用例说明 客户参与者通过注册获得进入彬使用系统的权限 参与者 客户 前置条件 无 后置条件 系统正确接收用户信息并保存到数据库 基本路径 发布注册申请系统显示注册页面客户填写相应信息并提交注册成功后可以进行其…

贷款投资决策和常用财务函数

前段时间上了一门excel操作的课&#xff0c;本文结合其中介绍财务函数以及投资决策分析相关的部分&#xff0c;对贷款中的现金流计算进行深入的分析。 以等额本息产品为例进行实操计算&#xff0c;假设某产品本金12000元&#xff0c;期限12&#xff0c;IRR利率24%。每期还款113…

生信分析进阶5 - 全外显子组变异检测和ANNOVAR注释Snakemake分析流程

基于yaml或ini配置文件&#xff0c;配置文件包含例如样本名称、参考基因组版本、exon capture bed文件路径、参考基因组路径和ANNOVAR注释文件等信息。 基于该流程可以实现全外显测序的fastq文件输入到得到最终变异VCF文件。 1. Snakemake分析流程基础软件安装 # conda安装 …