Difficulty | Source | Tags | ||
---|---|---|---|---|
Medium |
160 Days of Problem Solving |
|
The problem can be found at the following link: Question Link
Given a Binary Search Tree (BST) and a target value, check whether there exists a pair of nodes in the BST whose sum equals the given target.
7
/ \
3 8
/ \ \
2 4 9
Target = 12

True
In the given BST, there exist two nodes (8 and 4) that sum up to 12.
9
/ \
5 10
/ \ \
2 6 12
Target = 23

False
No pair of nodes in the BST sum up to 23.
$(1 \leq \text{Number of Nodes} \leq 10^5)$ $(1 \leq \text{target} \leq 10^6)$
- Convert BST to sorted array using inorder traversal.
- Use two-pointer approach (left and right) to find the target sum efficiently.
- Perform an inorder traversal and store the BST elements in a sorted list.
- Use two pointers (
left
at the start,right
at the end) and check the sum:- If
arr[left] + arr[right] == target
, returntrue
. - If
arr[left] + arr[right] < target
, moveleft++
. - If
arr[left] + arr[right] > target
, moveright--
.
- If
- If no such pair exists, return
false
.
- Expected Time Complexity:
O(N)
, since we traverse each node once. - Expected Auxiliary Space Complexity:
O(N)
, due to storing the inorder traversal.
class Solution {
public:
bool findTarget(Node* root, int target) {
vector<int> inorder;
function<void(Node*)> traverse = [&](Node* node) {
if (!node) return;
traverse(node->left);
inorder.push_back(node->data);
traverse(node->right);
};
traverse(root);
int left = 0, right = inorder.size() - 1;
while (left < right) {
int sum = inorder[left] + inorder[right];
if (sum == target) return true;
sum < target ? left++ : right--;
}
return false;
}
};
- Use DFS to traverse the tree while maintaining a hash set of visited values.
- Check if (target - current node value) exists in the set, if yes, return
true
. - Insert the current node value into the set and continue.
class Solution {
public:
bool findTarget(Node* root, int target) {
unordered_set<int> seen;
return dfs(root, target, seen);
}
bool dfs(Node* root, int target, unordered_set<int>& seen) {
if (!root) return false;
if (seen.count(target - root->data)) return true;
seen.insert(root->data);
return dfs(root->left, target, seen) || dfs(root->right, target, seen);
}
};
πΉ Avoids extra space for storing inorder traversal
πΉ Uses Hash Set for O(1)
lookup
- Use two iterators: one for inorder (left to right) and one for reverse inorder (right to left).
- Move iterators towards each other until the pair is found or iterators cross.
class BSTIterator {
stack<Node*> st;
bool reverse;
public:
BSTIterator(Node* root, bool isReverse) {
reverse = isReverse;
pushAll(root);
}
int next() {
Node* node = st.top(); st.pop();
if (!reverse) pushAll(node->right);
else pushAll(node->left);
return node->data;
}
bool hasNext() { return !st.empty(); }
private:
void pushAll(Node* node) {
while (node) {
st.push(node);
node = reverse ? node->right : node->left;
}
}
};
class Solution {
public:
bool findTarget(Node* root, int target) {
BSTIterator l(root, false), r(root, true);
int i = l.next(), j = r.next();
while (i < j) {
int sum = i + j;
if (sum == target) return true;
sum < target ? i = l.next() : j = r.next();
}
return false;
}
};
πΉ Optimized space using O(H)
stack instead of O(N)
vector
πΉ Uses BST Iterators for an efficient two-pointer search
Approach | β±οΈ Time Complexity | ποΈ Space Complexity | β‘ Method | β Pros | |
---|---|---|---|---|---|
Two-Pointer on Inorder Array | π’ O(N) |
π‘ O(N) |
Two Pointers | Simple and efficient | Extra space for list |
Hash Set (DFS) | π’ O(N) |
π‘ O(N) |
Hashing | Faster lookup, no sorting needed | Hashing overhead |
BST Iterator (Two-Pointer) | π‘ O(N^2) |
π’ O(H) |
Recursion | No extra storage used | Slow for large BSTs |
- For simplicity: β Two-Pointer on Inorder Array is easiest to understand.
- For faster lookups: β
Hash Set (
O(H)
space) avoids sorting overhead. - For minimal space: β
BST Iterator (
O(H)
space,O(N)
time) avoids extra space but is slow for large BSTs.
class Solution {
public boolean findTarget(Node root, int target) {
List<Integer> inorder = new ArrayList<>();
inorderTraversal(root, inorder);
int left = 0, right = inorder.size() - 1;
while (left < right) {
int sum = inorder.get(left) + inorder.get(right);
if (sum == target) return true;
if (sum < target) left++;
else right--;
}
return false;
}
private void inorderTraversal(Node node, List<Integer> inorder) {
if (node == null) return;
inorderTraversal(node.left, inorder);
inorder.add(node.data);
inorderTraversal(node.right, inorder);
}
}
class Solution:
def findTarget(self, root, target):
inorder = []
def inorderTraversal(node):
if not node:
return
inorderTraversal(node.left)
inorder.append(node.data)
inorderTraversal(node.right)
inorderTraversal(root)
left, right = 0, len(inorder) - 1
while left < right:
total = inorder[left] + inorder[right]
if total == target:
return True
if total < target:
left += 1
else:
right -= 1
return False
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: Any Questions. Letβs make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β