Given the root of a binary search tree and an integer k, return trueif there exist two elements in the BST such that their sum is equal tok, orfalseotherwise.
Example 1:
Input: root = [5,3,6,2,4,null,7], k = 9
Output: true
Example 2:
Input: root = [5,3,6,2,4,null,7], k = 28
Output: false
Constraints:
The number of nodes in the tree is in the range [1, 104].
-104 <= Node.val <= 104
root is guaranteed to be a valid binary search tree.
-105 <= k <= 105
Solutions
Solution 1
Thinking
Find two nodes summing to \(k\). Inorder plus two pointers works after collecting values.
A set of seen values during a walk is enough: if \(k-val\) is present, return true. The BST order is not required.
1 2 3 4 5 6 7 8 9101112131415161718
# Definition for a binary tree node.# class TreeNode:# def __init__(self, val=0, left=None, right=None):# self.val = val# self.left = left# self.right = rightclassSolution:deffindTarget(self,root:Optional[TreeNode],k:int)->bool:defdfs(root):ifrootisNone:returnFalseifk-root.valinvis:returnTruevis.add(root.val)returndfs(root.left)ordfs(root.right)vis=set()returndfs(root)
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */funcfindTarget(root*TreeNode,kint)bool{vis:=map[int]bool{}vardfsfunc(*TreeNode)booldfs=func(root*TreeNode)bool{ifroot==nil{returnfalse}ifvis[k-root.Val]{returntrue}vis[root.Val]=truereturndfs(root.Left)||dfs(root.Right)}returndfs(root)}
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */funcfindTarget(root*TreeNode,kint)bool{q:=[]*TreeNode{root}vis:=map[int]bool{}forlen(q)>0{forn:=len(q);n>0;n--{node:=q[0]q=q[1:]ifvis[k-node.Val]{returntrue}vis[node.Val]=trueifnode.Left!=nil{q=append(q,node.Left)}ifnode.Right!=nil{q=append(q,node.Right)}}}returnfalse}
Find two nodes whose values sum to \(k\). Inorder plus two pointers works after collecting every value. A set of values already seen is enough: if \(k\) minus the current value is present, return true. On a short tree one depth-first walk does this, and the BST order is not required.
The tree can contain \(10^4\) nodes. A left chain makes this walk recurse once per node and overflow the call stack.
Each node depends only on values already visited. The children do not need to return before the node is checked.
An explicit stack keeps that depth-first order. Pop a node, test \(k\) minus its value, then store the value and push the right child and the left child. The set belongs to this call only.
A hash set stores values already visited, and an explicit stack walks the tree depth-first. When a node is popped, return true if \(k\) minus its value is already in the set. Otherwise store the value and push the non-null right child and left child.
The time complexity is \(O(n)\), and the space complexity is \(O(n)\). Here, \(n\) is the number of nodes in the binary search tree.
1 2 3 4 5 6 7 8 910111213141516171819202122
# Definition for a binary tree node.# class TreeNode:# def __init__(self, val=0, left=None, right=None):# self.val = val# self.left = left# self.right = rightclassSolution:deffindTarget(self,root:Optional[TreeNode],k:int)->bool:vis=set()stk=[]ifrootisnotNone:stk.append(root)whilestk:node=stk.pop()ifk-node.valinvis:returnTruevis.add(node.val)ifnode.rightisnotNone:stk.append(node.right)ifnode.leftisnotNone:stk.append(node.left)returnFalse
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */funcfindTarget(root*TreeNode,kint)bool{vis:=map[int]bool{}stk:=[]*TreeNode{}ifroot!=nil{stk=append(stk,root)}forlen(stk)>0{node:=stk[len(stk)-1]stk=stk[:len(stk)-1]ifvis[k-node.Val]{returntrue}vis[node.Val]=trueifnode.Right!=nil{stk=append(stk,node.Right)}ifnode.Left!=nil{stk=append(stk,node.Left)}}returnfalse}