Given a Binary Search Tree and a sum. The task is to check if any triplet (group of 3 elements) exists in the BST with the given sum. Three nodes may not necessarily be distinct.
Examples:
Input : sum = 9
Output: true
Explanation: There exists a triplet {3, 3, 3} in the above given BST with sum 9.
Table of Content
[Naive approach] Convert tree to array - O(n^2) Time and O(n) Space
A simple approach will be to convert the BST to a sorted array and then find the triplet using three-pointers. This will take O(n) extra space where n is the number of nodes present in the Binary Search Tree. Please refer to Check if a triplet with given sum exists in BST for implementation.
We will solve this problem using a space-efficient method by reducing the additional space complexity to O(h) where h is the height of BST. For that, we will use the two pointer technique on BST.
[Expected Approach] Two Pointer technique on BST - O(n^2) Time and O(h) Space
The idea is to use the two pointer technique on BST. We will traverse all the nodes of the tree one by one and for each node, we will try to find a pair with a sum equal to (sum - curr->data) where 'curr' is the current node of the BST we are traversing. We will use a technique similar to the technique discussed in Pair with a given sum in BST.
Follow the steps below to solve the problem:
- Traverse each node of BST one by one and for each node:
- Create a forward and backward iterator for BST. Let's say the value of nodes they are pointing at are v1 and v2.
- Now at each step,
- If v1 + v2 = sum, we found a pair, thus we will increase the count by 1.
- If v1 + v2 is less than or equal to sum, we will make forward iterator point to the next element.
- If v1 + v2 is greater than sum, we will make backward iterator point to the previous element.
- We will continue the above while the left iterator doesn't point to a node with larger value than right node.
// C++ implementation of finding triplate with given
// target using two pointer technique on BST
#include <bits/stdc++.h>
using namespace std;
class Node {
public:
int data;
Node* left;
Node* right;
Node(int x) {
data = x;
left = right = nullptr;
}
};
bool existsPair(Node* root, int sum) {
stack<Node *> it1, it2;
// Initializing forward iterator
Node* c = root;
while (c != nullptr)
it1.push(c), c = c->left;
// Initializing backward iterator
c = root;
while (c != nullptr)
it2.push(c), c = c->right;
// Two pointer technique
while (it1.size() and it2.size()) {
// Variables to store values at
// it1 and it2
int v1 = it1.top()->data, v2 = it2.top()->data;
// Base case
if (v1 + v2 == sum)
return 1;
if (v1 > v2)
break;
// Moving forward pointer
if (v1 + v2 < sum) {
c = it1.top()->right;
it1.pop();
while (c != nullptr)
it1.push(c), c = c->left;
}
// Moving backward pointer
else {
c = it2.top()->left;
it2.pop();
while (c != nullptr)
it2.push(c), c = c->right;
}
}
return 0;
}
bool existsTriplet(Node* root, Node* curr, int sum) {
if (curr == nullptr)
return 0;
// Conditions for existence of a triplet
return (existsPair(root, sum - curr->data)
|| existsTriplet(root, curr->left, sum)
|| existsTriplet(root, curr->right, sum));
}
int main() {
// Binary search tree:
// 5
// / \
// 3 7
// / \ / \
// 2 4 6 8
Node* root = new Node(5);
root->left = new Node(3);
root->right = new Node(7);
root->left->left = new Node(2);
root->left->right = new Node(4);
root->right->left = new Node(6);
root->right->right = new Node(8);
int sum = 24;
if (existsTriplet(root, root, sum))
cout << "true";
else
cout << "false";
return 0;
}
// Java implementation of finding triplet with given
// target using two pointer technique on BST
import java.util.Stack;
class Node {
int data;
Node left, right;
Node(int x) {
data = x;
left = right = null;
}
}
class GfG {
static boolean existsPair(Node root, int sum) {
Stack<Node> it1 = new Stack<>();
Stack<Node> it2 = new Stack<>();
// Initializing forward iterator
Node c = root;
while (c != null) {
it1.push(c);
c = c.left;
}
// Initializing backward iterator
c = root;
while (c != null) {
it2.push(c);
c = c.right;
}
// Two pointer technique
while (!it1.isEmpty() && !it2.isEmpty()) {
// Variables to store values at
// it1 and it2
int v1 = it1.peek().data, v2 = it2.peek().data;
// Base case
if (v1 + v2 == sum)
return true;
if (v1 > v2)
break;
// Moving forward pointer
if (v1 + v2 < sum) {
c = it1.peek().right;
it1.pop();
while (c != null) {
it1.push(c);
c = c.left;
}
}
// Moving backward pointer
else {
c = it2.peek().left;
it2.pop();
while (c != null) {
it2.push(c);
c = c.right;
}
}
}
return false;
}
static boolean existsTriplet(Node root, Node curr, int sum) {
if (curr == null)
return false;
// Conditions for existence of a triplet
return (existsPair(root, sum - curr.data)
|| existsTriplet(root, curr.left, sum)
|| existsTriplet(root, curr.right, sum));
}
public static void main(String[] args) {
// Binary search tree:
// 5
// / \
// 3 7
// / \ / \
// 2 4 6 8
Node root = new Node(5);
root.left = new Node(3);
root.right = new Node(7);
root.left.left = new Node(2);
root.left.right = new Node(4);
root.right.left = new Node(6);
root.right.right = new Node(8);
int sum = 24;
if (existsTriplet(root, root, sum))
System.out.println("true");
else
System.out.println("false");
}
}
# Python implementation of finding triplet with given
# target using two pointer technique on BST
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def existsPair(root, sum):
it1, it2 = [], []
# Initializing forward iterator
c = root
while c:
it1.append(c)
c = c.left
# Initializing backward iterator
c = root
while c:
it2.append(c)
c = c.right
# Two pointer technique
while it1 and it2:
# Variables to store values at
# it1 and it2
v1 = it1[-1].data
v2 = it2[-1].data
# Base case
if v1 + v2 == sum:
return True
if v1 > v2:
break
# Moving forward pointer
if v1 + v2 < sum:
c = it1.pop().right
while c:
it1.append(c)
c = c.left
# Moving backward pointer
else:
c = it2.pop().left
while c:
it2.append(c)
c = c.right
return False
def existsTriplet(root, curr, sum):
if curr is None:
return False
# Conditions for existence of a triplet
return (existsPair(root, sum - curr.data)
or existsTriplet(root, curr.left, sum)
or existsTriplet(root, curr.right, sum))
if __name__ == "__main__":
# Binary search tree:
# 5
# / \
# 3 7
# / \ / \
# 2 4 6 8
root = Node(5)
root.left = Node(3)
root.right = Node(7)
root.left.left = Node(2)
root.left.right = Node(4)
root.right.left = Node(6)
root.right.right = Node(8)
sum = 24
if existsTriplet(root, root, sum):
print("true")
else:
print("false")
// C# implementation of finding triplet with given
// target using two pointer technique on BST
using System;
using System.Collections.Generic;
class Node {
public int data;
public Node left, right;
public Node(int x) {
data = x;
left = right = null;
}
}
class GfG {
static bool ExistsPair(Node root, int sum) {
Stack<Node> it1 = new Stack<Node>();
Stack<Node> it2 = new Stack<Node>();
// Initializing forward iterator
Node c = root;
while (c != null) {
it1.Push(c);
c = c.left;
}
// Initializing backward iterator
c = root;
while (c != null) {
it2.Push(c);
c = c.right;
}
// Two pointer technique
while (it1.Count > 0 && it2.Count > 0) {
// Variables to store values at
// it1 and it2
int v1 = it1.Peek().data, v2 = it2.Peek().data;
// Base case
if (v1 + v2 == sum)
return true;
if (v1 > v2)
break;
// Moving forward pointer
if (v1 + v2 < sum) {
c = it1.Peek().right;
it1.Pop();
while (c != null) {
it1.Push(c);
c = c.left;
}
}
// Moving backward pointer
else {
c = it2.Peek().left;
it2.Pop();
while (c != null) {
it2.Push(c);
c = c.right;
}
}
}
return false;
}
static bool ExistsTriplet(Node root, Node curr, int sum) {
if (curr == null)
return false;
// Conditions for existence of a triplet
return (ExistsPair(root, sum - curr.data)
|| ExistsTriplet(root, curr.left, sum)
|| ExistsTriplet(root, curr.right, sum));
}
static void Main(string[] args) {
// Binary search tree:
// 5
// / \
// 3 7
// / \ / \
// 2 4 6 8
Node root = new Node(5);
root.left = new Node(3);
root.right = new Node(7);
root.left.left = new Node(2);
root.left.right = new Node(4);
root.right.left = new Node(6);
root.right.right = new Node(8);
int sum = 24;
if (ExistsTriplet(root, root, sum))
Console.WriteLine("true");
else
Console.WriteLine("false");
}
}
// JavaScript implementation of finding triplet with given
// target using two pointer technique on BST
class Node {
constructor(data) {
this.data = data;
this.left = null;
this.right = null;
}
}
function existsPair(root, sum) {
let it1 = [], it2 = [];
// Initializing forward iterator
let c = root;
while (c) {
it1.push(c);
c = c.left;
}
// Initializing backward iterator
c = root;
while (c) {
it2.push(c);
c = c.right;
}
// Two pointer technique
while (it1.length > 0 && it2.length > 0) {
// Variables to store values at
// it1 and it2
let v1 = it1[it1.length - 1].data;
let v2 = it2[it2.length - 1].data;
// Base case
if (v1 + v2 == sum) return true;
if (v1 > v2) break;
// Moving forward pointer
if (v1 + v2 < sum) {
c = it1.pop().right;
while (c) {
it1.push(c);
c = c.left;
}
}
// Moving backward pointer
else {
c = it2.pop().left;
while (c) {
it2.push(c);
c = c.right;
}
}
}
return false;
}
function existsTriplet(root, curr, sum) {
// If current node is NULL
if (curr === null) return false;
// Conditions for existence of a triplet
return (existsPair(root, sum - curr.data) ||
existsTriplet(root, curr.left, sum) ||
existsTriplet(root, curr.right, sum));
}
// Binary search tree:
// 5
// / \
// 3 7
// / \ / \
// 2 4 6 8
let root = new Node(5);
root.left = new Node(3);
root.right = new Node(7);
root.left.left = new Node(2);
root.left.right = new Node(4);
root.right.left = new Node(6);
root.right.right = new Node(8);
let sum = 24;
if (existsTriplet(root, root, sum)) {
console.log("true");
} else {
console.log("false");
}
Output
true
