题目描述
题干:
给定一个二叉搜索树 root 和一个目标结果 k,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 true。
示例 1:
输入: root = [5,3,6,2,4,null,7], k = 9
输出: true
示例 2:
输入: root = [5,3,6,2,4,null,7], k = 28
输出: false
题解思路
这次的判断两数之和和二叉搜索树结合,我们可以借助二叉搜索树的性质来解决两数之和的问题
如果我们采用传统方式,我们可以直接深度或者广度优先遍历结合递归、队列和哈希表判断
如果借助二叉搜索树中序遍历元素会顺序排序的规律,也可以采用双指针的方式判断
也可以将双指针直接放置在二叉搜索树上进行移动搜索,不过需要找好左右指针的下一个节点的位置
正确代码
class FindTargetSolution {
Set<Integer> set = new HashSet<>();
List<Integer> list = new ArrayList<>();
// 深度优先遍历 + 哈希表
public boolean findTarget01(TreeNode root, int k) {
if (root == null) {
return false;
}
if (set.contains(k - root.val)) {
return true;
}
set.add(root.val);
return findTarget01(root.left, k) || findTarget01(root.right, k);
}
// 广度优先遍历 + 哈希表
public boolean findTarget02(TreeNode root, int k) {
ArrayDeque<Object> queue = new ArrayDeque<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode node = (TreeNode) queue.poll();
if (set.contains(k - node.val)) {
return true;
}
set.add(node.val);
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
return false;
}
// 深度优先遍历 + 中序遍历 + 双指针
public boolean findTarget03(TreeNode root, int k) {
inorderTraversal(root);
int left = 0, right = list.size() - 1;
while (left < right) {
if (list.get(left) + list.get(right) == k) {
return true;
} if (list.get(left) + list.get(right) < k) {
left++;
} else {
right--;
}
}
return false;
}
private void inorderTraversal(TreeNode node) {
if (node == null) {
return;
}
inorderTraversal(node.left);
list.add(node.val);
inorderTraversal(node.right);
}
// 迭代 + 中序遍历 + 双指针
public boolean findTarget04(TreeNode root, int k) {
TreeNode left = root, right = root;
ArrayDeque<TreeNode> leftStack = new ArrayDeque<>();
ArrayDeque<TreeNode> rightStack = new ArrayDeque<>();
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) {
if (left.val + right.val == k) {
return true;
}
if (left.val + right.val < k) {
left = getLeft(leftStack);
} else {
right = getRight(rightStack);
}
}
return false;
}
private TreeNode getLeft(Deque<TreeNode> stack) {
TreeNode root = stack.pop();
TreeNode node = root.right;
while (node != null) {
stack.push(node);
node = node.left;
}
return root;
}
private TreeNode getRight(Deque<TreeNode> stack) {
TreeNode root = stack.pop();
TreeNode node = root.left;
while (node != null) {
stack.push(node);
node = node.right;
}
return root;
}
}
总结
两数之和问题作为leetCode的第一个问题,当时只会暴力求解的我根本不知道用哈希表存储差值来简化计算
到现在第四道两数之和已经掺杂了各种数据结构,也知晓了各种解题思路,也算是对自己的一种鼓励吧
但是算法的路要有很长的路要走,学到现在也只是冰山一角而已,路漫漫其修远兮,吾将上下而求索。