(简单)剑指Offer II 056. 二叉搜索树中两个节点的和 Java

news2024/11/23 4:48:35

在这里插入图片描述

方法一:深度优先搜索+哈希表

使用深度优先搜索的方式遍历整棵树,用哈希表记录遍历过的节点的值

对于一个值为x的节点,检查哈希表中是否存在k-x即可。如果存在对应的元素,那么我们就可以在该树上找到两个节点的和为k;否则,将x放入到哈希表中

如果遍历完整棵树都不存在对应的元素,那么该树上不存在两个和为k的节点

import java.util.HashSet;
import java.util.Set;

class Solution {

    Set<Integer> set = new HashSet<>();

    public boolean findTarget(TreeNode root, int k) {
        if (root == null) {
            return false;
        }
        if (set.contains(k - root.val)) {
            return true;
        }
        set.add(root.val);
        return findTarget(root.left, k) || findTarget(root.right, k);
    }
}

复杂度分析:

  • 时间复杂度:O(n),其中n为二叉树的大小。需要遍历整棵树一次。
  • 空间复杂度:O(n),其中n为二叉树的大小。主要为哈希表的开销,最坏情况下需要将每个节点加入哈希表一次。
    在这里插入图片描述
    方法二:广度优先搜索 + 哈希表

使用广度优先搜索的方式遍历整棵树,用哈希表记录遍历过的节点值

首先,创建一个哈希表和一个队列,将根节点加入队列中,然后执行以下步骤:(层序遍历)

  1. 从队列中取出队头,假设其值为x
  2. 检查哈希表中是否存在k-x,如果存在返回true
  3. 否则,将该节点的值加入哈希表,将该节点的左右非空节点加入队尾
  4. 重复以上步骤,直到队列为空
  5. 如果队列为空,说明树上不存在两个和为k的节点,返回false
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

class Solution {
    public boolean findTarget(TreeNode root, int k) {
        Set<Integer> set = new HashSet<>();
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if (set.contains(k - node.val)) {
                return true;
            }
            set.add(node.val);
            if (node.left != null) {
                queue.add(node.left);
            }
            if (node.right != null) {
                queue.add(node.right);
            }
        }
        return false;
    }
}

复杂度分析:

  • 时间复杂度:O(n),其中n为二叉搜索树的大小。需要遍历整棵树一次。
  • 空间复杂度:O(n),其中n为二叉搜索树的大小。主要为哈希表和队列的开销,最坏情况下需要将每个节点加入哈希表和队列各一次。

在这里插入图片描述

方法三:深度优先搜索+中序遍历+双指针

二叉搜索树的中序遍历是升序排列的,可以将该二叉搜索树的中序遍历的结果记录下来,得到一个升序数组。

具体地,使用两个指针分别指向数组的头尾,当两个指针指向的元素之和小于k时,让左指针右移;当两个指针指向的元素之和大于k时,让右指针左移;当两个指针指向的元素之和等于k时,返回true

最终,当左指针和右指针重合时,树上不存在两个和为k的节点,返回false

import java.util.ArrayList;
import java.util.List;

class Solution {

    List<Integer> list = new ArrayList<>();

    public boolean findTarget(TreeNode root, int k) {
        inorder(root);
        int n = list.size();
        int left = 0;
        int right = n - 1;
        while (left < right && right < n) {
            int val = list.get(left) + list.get(right);
            if (val < k) {
                left++;
            } else if (val > k) {
                right--;
            } else {
                return true;
            }
        }
        return false;
    }

    public void inorder(TreeNode root) {
        if (root == null) {
            return;
        }
        inorder(root.left);
        list.add(root.val);
        inorder(root.right);
    }
}

复杂度分析:

  • 时间复杂度:O(n),其中n为二叉搜索树的大小。我们需要遍历这棵树一次,并对得到的升序数组使用双指针遍历。
  • 空间复杂度:O(n),其中n为二叉搜索树的大小。主要为升序数组的开销。

在这里插入图片描述
方法四:迭代 + 中序遍历 + 双指针

在方法三中,是在中序遍历得到的数组上进行双指针,这样需要消耗O(n)的空间,实际上可以将双指针的移动理解为在树上的遍历过程的一次移动。因为递归方法较难控制移动过程,因此可以使用迭代的方式进行遍历。

具体地,对于每一个指针新建一个栈。初始,让左指针移动到树的最左端点,并将路径保存在栈中,接下来依据栈来O(1)地计算出左指针的下一个位置。右指针也是同理。

计算下一个位置时,首先将位于栈顶的当前节点从栈中弹出,此时,首先判断当前节点是否存在右子节点,如果存在,那么将右子节点的最左子树加入到栈中;否则就完成了当前层的遍历,无需进一步修改栈的内容,直接回溯到上一层即可。

import java.util.Deque;
import java.util.LinkedList;
import java.util.Stack;

class Solution {
    public boolean findTarget(TreeNode root, int k) {
        TreeNode left = root;
        TreeNode right = root;
        Stack<TreeNode> leftStack = new Stack<>();
        Stack<TreeNode> rightStack = new Stack<>();

        leftStack.push(left);
        while (left.left != null) {
            leftStack.push(left.left);
            left = left.left;
        }

        rightStack.push(right);
        while (right.right != null) {
            rightStack.push(right.right);
            right = right.right;
        }

        while (left != right) {
            int val = left.val + right.val;
            if (val > k) {
                right = getRight(rightStack);
            } else if (val < k) {
                left = getLeft(leftStack);
            } else {
                return true;
            }
        }
        return false;
    }

    private TreeNode getLeft(Stack<TreeNode> leftStack) {
        TreeNode root = leftStack.pop();
        TreeNode node = root.right;
        while (node != null) {
            leftStack.push(node);
            node = node.left;
        }
        return root;
    }

    private TreeNode getRight(Stack<TreeNode> rightStack) {
        TreeNode root = rightStack.pop();
        TreeNode node = root.left;
        while (node != null) {
            rightStack.push(node);
            node = node.right;
        }
        return root;
    }

}

复杂度分析:

  • 时间复杂度:O(n),其中n为二叉搜索树的大小。在双指针的过程中,实际上遍历了整棵树一次。
  • 空间复杂度:O(n),其中n为二叉搜索树的大小。主要为栈的开销,最坏情况下二叉搜索树为一条链,需要O(n)的栈空间。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

河流垃圾检测Y8S

【免费】河流垃圾检测Y8M&#xff0c;只需要OPENCV资源-CSDN文库 采用YOLOV8训练&#xff0c;得到PT模型&#xff0c;然后直接转ONNX&#xff0c;使用OPENCV的DNN&#xff0c;不需要其他依赖&#xff0c;支持C/PYTHON

Hadoop 之 分布式集群配置与使用(三)

Hadoop 之 分布式集群 一.集群实例创建二.配置1.创建三个虚拟机&#xff08;Anolis&#xff09;1.修改 HostName2.配置免密登录&#xff0c;配置前 2.配置命名节点1.在 nd1 / nd2 部署 hadoop2.配置 3.查看集群信息 三.测试 一.集群实例创建 以三个 Hadoop 实例创建集群&#…

对战五子棋——网页版

目录 一、项目简介 二、用户模块 1、创建用户实体类 2、编写userMapper接口文件 3、实现userMapper.xml文件 4、对用户密码进行加密 5、实现用户登录功能 6、实现用户注册功能 三、实现用户匹配模块 1、展示用户个人信息 2、匹配请求类 3、匹配响应类 4、创…

郭东白的架构课学习笔笔记(1)

1.架构师的品质 自信和勇气&#xff08;正确的废话&#xff09;拥有战略意图&#xff0c;所谓战略意图&#xff0c;就是拥有与其资源和能力极不相称的雄心壮志。使用演绎法寻找架构原理&#xff0c;而不是归纳法。 2.如何提升自己的架构能力 向身边比自己厉害的优秀架构师或…

【网络安全带你练爬虫-100练】第14练:文件内容的读取、取出

目录 一、目标1&#xff1a;把文件内容遍历取出 二、目标2&#xff1a;把文件内容全部取出 三、网络安全O 一、目标1&#xff1a;把文件内容遍历取出 &#xff08;1&#xff09;如果文件脚本在不同目录 file_path "path/to/your/file.txt" # 替换为你的文件路径…

【Gradle】Gradle之JVM进程详解

个人主页&#xff1a;金鳞踏雨 个人简介&#xff1a;大家好&#xff0c;我是金鳞&#xff0c;一个初出茅庐的Java小白 目前状况&#xff1a;22届普通本科毕业生&#xff0c;几经波折了&#xff0c;现在任职于一家国内大型知名日化公司&#xff0c;从事Java开发工作 我的博客&am…

【机密计算组织】机密计算联盟

一、简介 1.1 机密计算联盟与成员 2019年8月22日&#xff0c;Linux基金会宣布多家巨头企业组建“机密计算联盟”&#xff08;Confidential Computing Consortium&#xff09;&#xff0c;该基金将负责对联盟活动进行监督。机密计算联盟专门针对云服务及硬件生态&#xff0c;致…

SpringBoot中注入ServletFilterListener

1.基本介绍 文档&#xff1a;SpringBoot中注入Servlet&Filter&Listener 考虑到实际开发业务非常复杂和兼容问题&#xff0c;SpringBoot支持将Servlet、Filter、Listener注入spring容器中&#xff0c;成为Spring Bean也就是说&#xff0c;SpringBoot开放了和原生WEB组件…

关于初识MySQL数据库以及MySQL的基本使用

文章目录 什么是数据库什么是MySQL为什么要有数据库 MySQL基本使用连接mysql查看当前服务器对应的数据库创建数据库进入某个数据库建立一张表向表中插入数据查询表中的数据 服务器&#xff0c;数据库&#xff0c;表之间的关系数据逻辑存储MySQL架构SQL语句分类存储引擎 什么是数…

vue-cesium的基本使用【一】

最近的项目中用到了cesium,也了解了一点关于cesium的知识&#xff0c;打点、 标绘、等等基础的功能点&#xff0c;但是在开发过程中使用原生的cesium编写对于初学者还是有点难度&#xff0c;为此&#xff0c;找到关于对cesium进行二次封装的开源项目vue-cesium,本次文章主要记录…

Git原理与基本操作(含安装教程)

Git Git初识Git安装Linux-centosLinux-ubuntu Git基本操作git int配置Git 认识⼯作区、暂存区、版本库添加⽂件--场景⼀git add、git commitgit log 查看.git⽂件git cat-file 添加⽂件--场景⼆修改⽂件git statusgit diff [file]、git diff HEAD -- [file] 版本回退git resetg…

聊一下2023前端状况

2023已过大半&#xff0c;也是疫情后开放的第一年&#xff0c;想必大家都能感受到 各行各业一定程度上都在萎缩&#xff0c;线下一些工厂招聘&#xff0c;喊着90年以前的&#xff0c;可以回家了的 今年出现频率最高的一词就是裁员&#xff0c;失业&#xff0c;大学生慢就业 互联…

【从零开始学习Linux】背景知识与获取环境

哈喽&#xff0c;哈喽&#xff0c;大家好~ 我是你们的老朋友&#xff1a;保护小周ღ 本期给大家带来的是 Linux 操作系统的简介&#xff0c;以及如何获取一个Linux 的环境&#xff0c;作为Linux 章节起始篇&#xff0c;如果不妥之处&#xff0c;欢迎批评指正~ 本期收录于博主…

谷粒商城第二篇服务功能-商品服务-三级分类

商品服务三级分类工程初始化及查询搭建 在数据库中插入数据 1.controller类 RestController RequestMapping("product/category") public class CategoryController {Autowiredprivate CategoryService categoryService;/*** 查出所有分类以及子分类&#xff0c;…

前端Vue自定义可自由滚动新闻栏tabs选项卡标签栏标题栏组件

随着技术的发展&#xff0c;开发的复杂度也越来越高&#xff0c;传统开发方式将一个系统做成了整块应用&#xff0c;经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改&#xff0c;造成牵一发而动全身。 通过组件化开发&#xff0c;可以有效实现…

vue3.0之组合API有哪些(详解)

vue3.0之组合API有哪些 一、setup函数二、生命周期三、reactive函数四、toRef函数五、toRefs函数六、ref函数七、知识运用案例八、computed函数九、watch函数十、ref属性十一、父子通讯1.父传子2.子传父 十二、依赖注入十三、补充 v-model语法糖(简写)十四、补充 mixins语法 一…

【档案专题】三、电子档案管理系统

导读&#xff1a;主要针对电子档案管理系统相关内容介绍。对从事电子档案管理信息化的职业而言&#xff0c;不断夯实电子档案管理相关理论基础是十分重要。只有通过不断梳理相关知识体系和在实际工作当中应用实践&#xff0c;才能走出一条专业化加职业化的道路&#xff0c;从而…

el-cascader级联选择器那些事

el-cascader级联选择器那些事 1、获取选中的节点及其所有上级 vue3element-plusts 1、获取选中的节点及其所有上级 使用cascader组件提供的getCheckedNodes() <el-cascader :options"options" :show-all-levels"false" change"changeCascader&q…

cocosCreator笔记 之Spine了解

版本&#xff1a; 3.4.0 参考&#xff1a; Spine 骨骼动画资源 Spine Skeleton组件 cocosLua 之 骨骼动画 简介 使用spine动画&#xff0c;cocosCreator目前支持的版本&#xff1a; creator版本spine版本V3.0 及以上v3.8&#xff08;原生平台不支持特定版本 v3.8.75&…

北京银行发放门头沟区首笔知识产权质押贷款

6月&#xff0c;位于北京中关村门头沟科技园、专注于研制工业母机的民营企业——北京精雕科技集团有限公司&#xff08;以下简称“精雕科技集团”&#xff09;&#xff0c;因生产经营急需资金&#xff0c;但是由于缺乏抵押物而陷入了融资困境。“精雕科技集团与北京银行合作已长…