给定一个二叉搜索树的 根节点 root 和一个整数 k , 请判断该二叉搜索树中是否存在两个节点它们的值之和等于 k 。假设二叉搜索树中节点的值均唯一。
方法一:深度优先搜索+哈希表
使用深度优先搜索遍历整棵树,用哈希表记录遍历过的节点的值
代码
class Solution:
def __init__(self):
self.s = set()
def findTarget(self, root: Optional[TreeNode], k: int) -> bool:
if root is None:
return False
if k - root.val in self.s:
return True
self.s.add(root.val)
return self.findTarget(root.left, k) or self.findTarget(root.right, k)
方法二:广度优先搜索+哈希表
使用广度优先搜索的方式遍历整棵树,用哈希表记录遍历过的节点的值。
具体地,我们首先创建一个哈希表和一个队列,将根节点加入队列中,然后执行以下步骤:
- 从队列中取出队头,假设其值为 x;
- 检查哈希表中是否存在 k - x,如果存在,返回True;
- 否则,将该节点的左右的非空子节点加入队尾;
- 重复以上步骤,直到队列为空;
- 如果队列为空,说明树上不存在两个和为 kk 的节点,返回False。
代码
class Solution:
def findTarget(self, root: Optional[TreeNode], k: int) -> bool:
s = set()
q = deque([root])
while q:
node = q.popleft()
if k - node.val in s:
return True
s.add(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
return False
方法三:深度优先搜索 + 中序遍历 + 双指针
注意到二叉搜索树的中序遍历是升序排列的,我们可以将该二叉搜索树的中序遍历的结果记录下来,得到一个升序数组。
这样该问题即转化为「167. 两数之和 II - 输入有序数组」。我们可以使用双指针解决它。
具体地,我们使用两个指针分别指向数组的头尾,当两个指针指向的元素之和小于 k 时,让左指针右移;当两个指针指向的元素之和大于 k时,让右指针左移;当两个指针指向的元素之和等于 k 时,返回True。
最终,当左指针和右指针重合时,树上不存在两个和为 k 的节点,返回False。
代码
class Solution:
def findTarget(self, root: TreeNode, k: int) -> bool:
arr = []
def inorderTraversal(node: Optional[TreeNode]) -> None:
if node:
inorderTraversal(node.left)
arr.append(node.val)
inorderTraversal(node.right)
inorderTraversal(root)
l, r = 0, len(arr) - 1
while l < r:
if arr[l] + arr[r] == k:
return True
elif arr[l] + arr[r] > k:
r -= 1
elif arr[l] + arr[r] < k:
l += 1
return False