查找两个 BST 中和等于给定值 x 的对2025年3月17日 | 阅读 12 分钟 问题陈述 给定两个 BST,分别有 x1 和 x2 个不同的节点,要求找出两个节点的值,使其和恰好等于给定值 x。 同样尝试实现此方法的代码 方法 1 要在两个二叉搜索树(BST)中识别数对,您可以执行以下步骤,无需担心抄袭问题 - 对于 BST 1 中的每个节点值 'a',执行搜索以在 BST 2 中查找值 '(x - a)'。
- 如果找到所需值,则增加计数以跟踪数对。
上述方法的 Java 实现 输出  说明 插入方法 - insert 方法用于将具有给定值的新节点插入 BST。它确保根据节点值将节点添加到适当的位置。
countPairsWithSum 方法 - countPairsWithSum 方法以两个 BST(root1 和 root2)和一个目标和(targetSum)作为输入。
- 它使用一个集合(valueSet)来存储第二个 BST(root2)中的值,并使用一个栈(stack)进行迭代遍历。
- 该方法遍历 root2 并用其值填充 valueSet,为后续的数对计数做准备。
- 然后它初始化一个计数器来跟踪数对,并遍历 root1 以搜索与 valueSet 中的值组合形成目标和的数对。
- 如果找到一个数对,则计数器递增。
方法 2 - 从其最小值到最大值遍历第一个 BST (BST 1)。这可以通过迭代中序遍历完成,该遍历以升序访问节点。
- 同时,从其最大值到最小值遍历第二个 BST (BST 2)。这是通过反向中序遍历实现的,以降序访问节点。
- 在遍历两个 BST 的同时,在遍历的给定点处将 BST 1 和 BST 2 中相应节点的值相加。
- 如果这些节点值的和等于目标值 'x',则增加计数以跟踪数对。
- 如果和小于 'x',则移动到 BST 1 中当前节点的后继节点,以潜在地增加和。
- 如果和大于 'x',则移动到 BST 2 中当前节点的前驱节点,以潜在地减少和。
- 继续这些操作,直到其中一个遍历完成。
该方法有效地在两个 BST 中找到和等于目标值 'x' 的节点对,是解决此问题的常用方法。 算法 - 将计数初始化为 0。
- 初始化两个空栈,stack1 用于 BST1,stack2 用于 BST2。
- 同时开始以升序遍历 BST1 并以降序遍历 BST2。
- 将 curr1 初始化为 BST1 中最左侧的节点(最小值节点)。
- 将 curr2 初始化为 BST2 中最右侧的节点(最大值节点)。
- 当 curr1 和 curr2 都不为 null 或当 stack1 和 stack2 都不为空时,执行以下操作
- 以升序(中序)遍历 BST1 并将节点压入 stack1
- 当 curr1 不为 null 时,将 curr1 压入 stack1,并将 curr1 更新为 curr1.left。
- 以降序(反向中序)遍历 BST2 并将节点压入 stack2
- 当 curr2 不为 null 时,将 curr2 压入 stack2,并将 curr2 更新为 curr2.right。
- 在循环中:
- 如果 stack1 为空或 stack2 为空,则中断循环,因为其中一个遍历已完成。
- 从 stack1 和 stack2 中弹出顶部节点(top1 和 top2)。
- 计算和为 sum = top1.value + top2.value。
- 如果 sum 等于 'x'
- 如果 sum 小于 'x'
- 移动到 BST1 中 top1 的中序后继节点
- 将 curr1 设置为 top1.right。
- 如果 sum 大于 'x'
- 移动到 BST2 中 top2 的中序前驱节点
- 将 curr2 设置为 top2.left。
- 返回计数,作为两个 BST 中和等于 'x' 的数对总数。
- 算法结束。
上述方法的 Java 实现 输出  时间复杂度:O(n1+n2) 空间复杂度:O(h1+h2) 方法 3 利用递归策略解决此问题,即遍历 BST1,对于遇到的每个节点,计算 BST2 中的差值 (x - root1.data),然后增加计数器以跟踪出现次数。 上述方法的 Java 实现 输出  时间复杂度: 代码的时间复杂度为 O(n1 * n2),因为它涉及到遍历 BST1 中的每个节点,并且对于每个节点,遍历 BST2 以确定是否存在与给定差值匹配的数对。 辅助空间: 辅助空间复杂度为 O(h1 + h2),其中 h1 表示 BST1 的高度,h2 表示 BST2 的高度。此空间是递归遍历期间函数调用堆栈所需的,它随着相应树的高度而增加。 方法 4: 利用 BST 迭代器的概念 两个类 InorderSuccessorIterator 和 InorderPredecessorIterator,分别用于中序和反向中序行为 每个类将包含三个函数 hasNext: 只要遍历正在进行,就返回 true。 next: 将指针移动到下一个节点。 peek: 提供当前遍历中的当前节点。 在建立这两个类的两个实例后,当两个类都有下一个节点时执行迭代器。在每次迭代中计算总和。如果总和等于 x,则通过推进 iterator1 和 iterator2 的下一个指针来继续。如果总和大于 x,则递增 iterator2 的下一个指针;否则,当总和小于 x 时,递增 iterator1 的下一个指针。 上述方法的 Java 实现 输出  时间复杂度: O(n1 + n2),其中 n1 和 n2 分别是第一棵树和第二棵树中的节点总数。 辅助空间: O(h1 + h2),其中 h1 表示第一棵树的高度,h2 表示第二棵树的高度。
|