Related: LeetCode 653 - Two Sum IV - Input is a BST
Find a pair with given sum in a Balanced BST | GeeksforGeeks
Given a Balanced Binary Search Tree and a target sum, write a function that returns true if there is a pair with sum equals to target sum, otherwise return false. Expected time complexity is O(n) and only O(Logn) extra space can be used.
Key Point: reverse inorder traversal, inorder and reverse inorder at same time.
1. Convert the BST into a sorted doubly linklist.(increasing order)
http://buttercola.blogspot.com/2015/11/zenefits-2sum-in-bst.html
Read full article from Find a pair with given sum in a Balanced BST | GeeksforGeeks
Find a pair with given sum in a Balanced BST | GeeksforGeeks
Given a Balanced Binary Search Tree and a target sum, write a function that returns true if there is a pair with sum equals to target sum, otherwise return false. Expected time complexity is O(n) and only O(Logn) extra space can be used.
Key Point: reverse inorder traversal, inorder and reverse inorder at same time.
The solution discussed below takes O(n) time, O(Logn) space and doesn’t modify BST.
Reverse Inorder Traversal
We traverse BST in Normal Inorder and Reverse Inorder simultaneously. In reverse inorder, we start from the rightmost node which is the maximum value node. In normal inorder, we start from the left most node which is minimum value node
A space optimized solution is discussed in previous post. The idea was to first in-place convert BST to Doubly Linked List (DLL), then find pair in sorted DLL in O(n) time. This solution takes O(n) time and O(Logn) extra space, but it modifies the given BST.
Also check code from http://algorithmsandme.blogspot.com/2013/08/binary-tree-property-two-numbers-which.html
Java Code: http://yuanhsh.iteye.com/blog/2209411
Similar code: http://prismoskills.appspot.com/lessons/Binary_Trees/Find_a_pair_with_given_sum.jsp
- public int[] findPair(TreeNode root, int target) {
- int[] pair = new int[]{-1, -1};
- Stack<TreeNode> leftStack = new Stack<>();
- Stack<TreeNode> rightStack = new Stack<>();
- boolean searchLeft = true, searchRight = true;
- TreeNode leftNode = root, rightNode = root;
- int leftVal = 0, rightVal = 0;
- while(true) {
- while(searchLeft) {
- if(leftNode != null) {
- leftStack.push(leftNode);
- leftNode = leftNode.left;
- } else {
- searchLeft = false;
- if(!leftStack.isEmpty()) {
- leftNode = leftStack.pop();
- leftVal = leftNode.val;
- leftNode = leftNode.right;
- }
- }
- }
- while(searchRight) {
- if(rightNode != null) {
- rightStack.push(rightNode);
- rightNode = rightNode.right;
- } else {
- searchRight = false;
- if(!rightStack.isEmpty()) {
- rightNode = rightStack.pop();
- rightVal = rightNode.val;
- rightNode = rightNode.left;
- }
- }
- }
- if(leftVal >= rightVal) {
- return pair;
- }
- if(leftVal + rightVal == target) {
- pair[0] = leftVal;
- pair[1] = rightVal;
- return pair;
- } else if(leftVal + rightVal > target) {
- searchRight = true;
- } else {
- searchLeft = true;
- }
- }
- }
Using Iterator: Inorder and Reverse Inorder Iterator.
bool hasTwoNodes(BinaryTreeNode* pRoot, int sum)
{
stack<BinaryTreeNode*> nextNodes, prevNodes;
buildNextNodes(pRoot, nextNodes);
buildPrevNodes(pRoot, prevNodes);
BinaryTreeNode* pNext = getNext(nextNodes);
BinaryTreeNode* pPrev = getPrev(prevNodes);
while(pNext != NULL && pPrev != NULL && pNext != pPrev)
{
int currentSum = pNext->m_nValue + pPrev->m_nValue;
if(currentSum == sum)
return true;
if(currentSum < sum)
pNext = getNext(nextNodes);
else
pPrev = getPrev(prevNodes);
}
return false;
}
void buildNextNodes(BinaryTreeNode* pRoot, stack<BinaryTreeNode*>& nodes)
{
BinaryTreeNode* pNode = pRoot;
while(pNode != NULL)
{
nodes.push(pNode);
pNode = pNode->m_pLeft;
}
}
void buildPrevNodes(BinaryTreeNode* pRoot, stack<BinaryTreeNode*>& nodes)
{
BinaryTreeNode* pNode = pRoot;
while(pNode != NULL)
{
nodes.push(pNode);
pNode = pNode->m_pRight;
}
}
BinaryTreeNode* getNext(stack<BinaryTreeNode*>& nodes)
{
BinaryTreeNode* pNext = NULL;
if(!nodes.empty())
{
pNext = nodes.top();
nodes.pop();
BinaryTreeNode* pRight = pNext->m_pRight;
while(pRight != NULL)
{
nodes.push(pRight);
pRight = pRight->m_pLeft;
}
}
return pNext;
}
BinaryTreeNode* getPrev(stack<BinaryTreeNode*>& nodes)
{
BinaryTreeNode* pPrev = NULL;
if(!nodes.empty())
{
pPrev = nodes.top();
nodes.pop();
BinaryTreeNode* pLeft = pPrev->m_pLeft;
while(pLeft != NULL)
{
nodes.push(pLeft);
pLeft = pLeft->m_pRight;
}
}
return pPrev;
}
// Returns true if a pair with target sum exists in BST, otherwise false
bool
isPairPresent(
struct
node *root,
int
target)
{
// Create two stacks. s1 is used for normal inorder traversal
// and s2 is used for reverse inorder traversal
struct
Stack* s1 = createStack(MAX_SIZE);
struct
Stack* s2 = createStack(MAX_SIZE);
// Note the sizes of stacks is MAX_SIZE, we can find the tree size and
// fix stack size as O(Logn) for balanced trees like AVL and Red Black
// tree. We have used MAX_SIZE to keep the code simple
// done1, val1 and curr1 are used for normal inorder traversal using s1
// done2, val2 and curr2 are used for reverse inorder traversal using s2
bool
done1 =
false
, done2 =
false
;
int
val1 = 0, val2 = 0;
struct
node *curr1 = root, *curr2 = root;
// The loop will break when we either find a pair or one of the two
// traversals is complete
while
(1)
{
// Find next node in normal Inorder traversal. See following post
while
(done1 ==
false
)
{
if
(curr1 != NULL)
{
push(s1, curr1);
curr1 = curr1->left;
}
else
{
if
(isEmpty(s1))
done1 = 1;
else
{
curr1 = pop(s1);
val1 = curr1->val;
curr1 = curr1->right;
done1 = 1;
}
}
}
// Find next node in REVERSE Inorder traversal. The only
// difference between above and below loop is, in below loop
// right subtree is traversed before left subtree
while
(done2 ==
false
)
{
if
(curr2 != NULL)
{
push(s2, curr2);
curr2 = curr2->right;
}
else
{
if
(isEmpty(s2))
done2 = 1;
else
{
curr2 = pop(s2);
val2 = curr2->val;
curr2 = curr2->left;
done2 = 1;
}
}
}
// If we find a pair, then print the pair and return. The first
// condition makes sure that two same values are not added
if
((val1 != val2) && (val1 + val2) == target)
{
printf
(
"\n Pair Found: %d + %d = %d\n"
, val1, val2, target);
return
true
;
}
// If sum of current values is smaller, then move to next node in
// normal inorder traversal
else
if
((val1 + val2) < target)
done1 =
false
;
// If sum of current values is greater, then move to next node in
// reverse inorder traversal
else
if
((val1 + val2) > target)
done2 =
false
;
// If any of the inorder traversals is over, then there is no pair
// so return false
if
(val1 >= val2)
return
false
;
}
}
public
boolean
twoSumBST(TreeNode root,
int
k) {
if
(root ==
null
) {
return
false
;
}
Stack<TreeNode> leftStack =
new
Stack<>();
Stack<TreeNode> rightStack =
new
Stack<>();
TreeNode p = root;
while
(p !=
null
) {
leftStack.push(p);
p = p.left;
}
p = root;
while
(p !=
null
) {
rightStack.push(p);
p = p.right;
}
p = leftStack.peek();
TreeNode q = rightStack.peek();
while
(p.val < q.val && p != q) {
if
(p.val + q.val == k) {
return
true
;
}
else
if
(p.val + q.val < k) {
leftStack.pop();
if
(p.right !=
null
) {
p = p.right;
while
(p !=
null
) {
leftStack.push(p);
p = p.left;
}
}
if
(leftStack.isEmpty()) {
return
false
;
}
p = leftStack.peek();
}
else
if
(p.val + q.val > k) {
rightStack.pop();
if
(q.left !=
null
) {
q = q.left;
while
(q !=
null
) {
rightStack.push(q);
q = q.right;
}
}
if
(rightStack.isEmpty()) {
return
false
;
}
q = rightStack.peek();
}
}
return
false
;
}