两数之和 IV -BST
给定一个二叉搜索树和一个目标结果,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 true。
示例1
输入:
5
/ \
3 6
/ \ \
2 4 7
Target = 9
输出: True
示例2
输入:
5
/ \
3 6
/ \ \
2 4 7
Target = 28
输出: False
方法一
思路
Set + 递归之倒推法: 准备一个Set集合当做容器,将二叉搜索树的所有数据放入Set集合中,递归每一个元素节点,判断集合中是否有一个数加上本节点的值为目标数据,有则返回true,如果递归遍历结束还没有返回true则返回false。
代码
// 倒推法
// 遍历树结构时 x是当前节点, y=k-x 是要找的第二个节点 是否存在
// 遍历过程用容器存储 以方便快速查找 set
// 时间复杂度O(n) 空间复杂度O(n)
public boolean findTarget(TreeNode root, int k) {
Set<Integer> set = new HashSet<>();
return f(root, k, set);
}
public boolean f(TreeNode root, int k, Set<Integer> set) {
// 判断如果节点为空则返回false
if (root == null) {
return false;
}
// 判断集合中是否有值与当前节点的值相加为k
int temp = k - root.val;
if (set.contains(temp)) {
return true;
}
// 如果没有则将当前节点的值存入集合继续遍历
set.add(root.val);
boolean left = f(root.left, k, set);
boolean right = f(root.right, k, set);
// 当递归结束,返回left分支或right分支(有一个返回true则符合结果)
return left || right;
}
方法二
思路
队列迭代: 使用队列迭代代替递归遍历,还是将二叉搜索树的各个节点值存入Set集合,通过队列依次迭代判断Set集合中是否存在于当前节点值相加为目标数组。
代码
// 使用迭代
// 用队列存储遍历的节点 处理一个节点后移除 当队列为空时 处理完成
// 时间复杂度O(n) 空间复杂度O(n)
public boolean findTarget1(TreeNode root, int k) {
Set<Integer> set = new HashSet<>();
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
// 只要队列不为空则一直循环
while (!queue.isEmpty()) {
// 将当前节点取出,判断set中是否有与其相加为k的数据
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;
}
方法三
思路
二叉树转有序列表双指针法: 这个方法优化了空间复杂度,因为二叉搜索树是有序的,先将二叉搜索树中序遍历转化为有序列表,然后双指针法找出结果,【有序数组两数之和 】,所谓双指针法就是定义两个指针,一个指向下表为0,另一个指向下标为长度-1,如果两个指针所指向的值相加大于目标值,则后面的指针自减,如果两个指针所指的指小于目标值,则前面的指针自增。如果当前面的指针大于等于后面的指针时,则说明条件不成立退出循环。
代码
// 二叉搜索树 可以转化为有序列表
// 在有序列表中 快速找到两个满足条件的值 使用的是头尾两个指针
// 双指针法
public boolean findTarget2(TreeNode root, int k) {
List<Integer> list = new ArrayList<>();
orderly(root, list);
int left = 0;
int right = list.size() - 1;
while (left < right) {
int s = list.get(left) + list.get(right);
if (s < k) {
left++;
}
if (s > k) {
right--;
}
if (s == k) {
return true;
}
}
return false;
}
public void orderly(TreeNode root, List<Integer> list) {
if (root == null) {
return;
}
orderly(root.left, list);
list.add(root.val);
orderly(root.right, list);
}