LeetCode653 两数之和 -输入二叉搜索树

devtools/2025/1/16 3:18:48/

探索二叉搜索树中的两数之和问题

算法数据结构的领域中,二叉搜索树(Binary Search Tree,BST)是一种非常重要的数据结构。它具有一些特殊的性质,使得我们可以高效地进行查找、插入和删除等操作。今天,我们来探讨一个与二叉搜索树相关的有趣问题:给定一个二叉搜索树 root 和一个目标结果 k,判断二叉搜索树中是否存在两个元素,它们的和等于给定的目标结果 k。如果存在,返回 true;否则,返回 false

一、二叉搜索树的特性回顾

二叉搜索树是一种有序的二叉树,对于树中的每个节点,其左子树的所有节点的值都小于该节点的值,而右子树的所有节点的值都大于该节点的值。这种特性使得二叉搜索树在很多算法问题中都有着独特的应用。

二、解题思路与实现

(一)中序遍历 + 双指针法

  1. 思路
    • 首先,我们知道二叉搜索树的中序遍历结果是一个有序的序列。所以,我们可以通过中序遍历将二叉搜索树的所有节点值存储到一个数组中。
    • 然后,利用双指针法,在这个有序数组中查找是否存在两个数的和等于目标值 k。我们设置一个左指针 left 指向数组的起始位置,一个右指针 right 指向数组的末尾位置。
    • 接着,通过比较 arr[left] + arr[right] 与 k 的大小关系来移动指针。如果和等于 k,则找到了符合条件的两个数;如果和小于 k,则将左指针右移一位,以增大和的值;如果和大于 k,则将右指针左移一位,以减小和的值。重复这个过程,直到左指针和右指针相遇。
  2. C 语言实现代码
#include <stdio.h>
#include <stdlib.h>// 定义二叉树节点结构体
struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;
};// 中序遍历二叉树,将节点值存入数组,并返回数组大小
int inorderTraversal(struct TreeNode* root, int* arr, int* index) {if (root == NULL) {return 0;}int leftCount = inorderTraversal(root->left, arr, index);arr[(*index)++] = root->val;int rightCount = inorderTraversal(root->right, arr, index);return leftCount + 1 + rightCount;
}// 函数用于判断二叉搜索树中是否存在两数之和等于目标值k
bool findTarget(struct TreeNode* root, int k) {int arrSize = 1000;  // 预先分配一定大小的数组空间,可根据实际情况调整或优化动态分配策略int* arr = (int*)malloc(arrSize * sizeof(int));if (arr == NULL) {printf("内存分配失败!\n");return false;}int index = 0;int count = inorderTraversal(root, arr, &index);int left = 0;int right = count - 1;while (left < right) {int sum = arr[left] + arr[right];if (sum == k) {free(arr);return true;} else if (sum < k) {left++;} else {right--;}}free(arr);return false;
}
  1. 复杂度分析
    • 时间复杂度:中序遍历二叉树的时间复杂度为O(n),其中 n 是二叉树节点的个数。后续在有序数组上使用双指针法查找的时间复杂度也是 O(n)。所以总的时间复杂度为O(n) 。
    • 空间复杂度:主要的空间消耗在于存储中序遍历结果的数组,在最坏情况下(二叉树是一条链时),数组长度为 n,所以空间复杂度是O(n)。此外,递归调用栈在最坏情况下也会达到O(n)的深度,综合来看空间复杂度是O(n) 。

(二)哈希表法

  1. 思路
    • 我们可以使用哈希表来记录已经遍历过的节点值。在遍历二叉搜索树的过程中,对于每个节点,计算其与目标值 k 的差值 target = k - node->val
    • 然后,在哈希表中查找是否存在这个差值。如果存在,说明找到了两个节点值之和等于 k;如果不存在,则将当前节点值插入到哈希表中,继续遍历下一个节点。
  2. C 语言实现代码(借助 uthash 库)
  3. #include <stdio.h>
    #include <stdlib.h>
    #include "uthash.h"// 定义二叉树节点结构体
    struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;
    };// 定义哈希表节点结构体
    struct HashNode {int key;UT_hash_handle hh;
    };// 函数用于判断二叉搜索树中是否存在两数之和等于目标值k
    bool findTarget(struct TreeNode* root, int k) {struct HashNode* hashTable = NULL;struct TreeNode* stack[100];  // 简单用数组模拟栈,可根据实际情况调整大小int top = -1;while (root!= NULL || top >= 0) {while (root!= NULL) {stack[++top] = root;root = root->left;}root = stack[top--];int target = k - root->val;struct HashNode* find;HASH_FIND_INT(hashTable, &target, find);if (find!= NULL) {return true;}// 将当前节点值加入哈希表struct HashNode* newNode = (struct HashNode*)malloc(sizeof(struct HashNode));newNode->key = root->val;HASH_ADD_INT(hashTable, key, newNode);root = root->right;}return false;
    }
  4. 复杂度分析
    • 时间复杂度:遍历二叉搜索树的每个节点,对于每个节点在哈希表中查找和插入操作的平均时间复杂度都接近常数,所以总的时间复杂度是O(n) ,其中 n 是二叉树节点的个数。
    • 空间复杂度:哈希表中最多会存储 n 个不同的节点值,所以空间复杂度是O(n)

三、总结

通过以上两种方法,我们都可以有效地解决在二叉搜索树中查找两数之和等于目标值的问题。中序遍历 + 双指针法利用了二叉搜索树的有序特性,而哈希表法则通过空间换时间的方式,提供了一种更直接的查找思路。在实际应用中,我们可以根据二叉树的规模、内存限制等因素来选择合适的方法。

希望这篇文章能帮助你更好地理解和解决这类与二叉搜索树相关的算法问题。如果你有任何疑问或建议,欢迎在评论区留言交流。


http://www.ppmy.cn/devtools/150221.html

相关文章

于交错的路径间:分支结构与逻辑判断的思维协奏

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。* 这一节内容很多&#xff0c;文章字数达到了史无前例的一万一&#xff0c;我们要来学习分支与循环结构中…

如何备考PostgreSQL中级认证

以下是一些备考 PostgreSQL 中级认证方法&#xff1a; 一、知识储备阶段 1、深入学习官方文档 PostgreSQL 官方文档是最权威的学习资源。仔细研读关于数据库架构、SQL 语法、数据类型、函数和操作符等基础部分。例如&#xff0c;了解 PostgreSQL 支持的丰富数据类型&#xff0c…

Git:Cherry-Pick 的使用场景及使用流程

前面我们说了 Git合并、解决冲突、强行回退等解决方案 >> 点击查看 这里再说一下 Cherry-Pick功能&#xff0c;Cherry-Pick不是merge&#xff0c;只是把部分功能代码Cherry-Pick到远程的目标分支 git cherry-pick功能简介&#xff1a; git cherry-pick 是用来从一个分…

策略模式详解与应用

策略模式&#xff08;Strategy Pattern&#xff09;&#xff0c;是一种行为型设计模式&#xff0c;它定义了一系列算法&#xff0c;并将每个算法封装起来&#xff0c;使它们可以互相替换&#xff0c;而应用程序可以在运行时选择使用哪一个算法。策略模式使得算法的变化独立于使…

深度学习的加速器:Horovod,让分布式训练更简单高效!

什么是 Horovod&#xff1f; Horovod 是 Uber 开发的一个专注于深度学习分布式训练的开源框架&#xff0c;旨在简化和加速多 GPU、多节点环境下的训练过程。它以轻量级、易用、高性能著称&#xff0c;特别适合需要快速部署分布式训练的场景。Horovod 的名字来源于俄罗斯传统舞…

【JVM-1】深入解析JVM:Java虚拟机的核心原理与工作机制

Java虚拟机&#xff08;JVM&#xff0c;Java Virtual Machine&#xff09;是Java技术的核心&#xff0c;它使得Java程序能够“一次编写&#xff0c;到处运行”。无论是Java开发者还是对技术感兴趣的爱好者&#xff0c;理解JVM的工作原理都是非常重要的。本文将深入探讨JVM的核心…

uniapp 使用 pinia 状态持久化

1.创建文件 stores -index.js -global.js2.对应文件内容 index.js 安装插件 npm i pinia-plugin-persistedstate import { createPinia } from pinia; import persist from pinia-plugin-persistedstate; const pinia createPinia(); pinia.use(persist); export default pi…

搜索引擎的设计与实现【源码+文档+部署讲解】

目 录 目 录 1 绪论 1.1 项目背景 1.2 国内外发展现状及分类 1.3 本论文组织结构介绍 2 相关技术介绍 2.1什么是搜索引擎 2.2 sqlserver数据库 2.3 Tomcat服务器 3 搜索引擎的基本原理 3.1搜索引擎的基本组成及其功能 3.2搜索引擎的详细工作流程 4 系统分析与…