给定一个平衡二进制搜索树和一个目标和,编写一个函数,如果存在一对总和等于目标和的函数,则返回true,否则返回false。预期的时间复杂度为O(n),并且只能使用O(Logn)多余的空间。不允许对二进制搜索树进行任何修改。请注意,平衡BST的高度始终为O(Logn)。
这个问题主要是前一篇文章的扩展。在这里,我们不允许修改BST。
蛮力解决方案是考虑BST中的每一对,并检查总和是否等于X。此解决方案的时间复杂度将为O(n ^ 2)。
更好的解决方案是创建一个辅助数组,并在该数组中存储BST的有序遍历。数组将被排序,因为BST的顺序遍历始终会产生排序的数据。一旦我们进行了有序遍历,就可以配对O(n)时间(有关详细信息,请参见此内容)。该解决方案的工作时间为O(n),但需要O(n)辅助空间。
Java
// Java code to find a pair with given sum
// in a Balanced BST
import java.util.ArrayList;
// A binary tree node
class Node {
int data;
Node left, right;
Node(int d)
{
data = d;
left = right = null;
}
}
class BinarySearchTree {
// Root of BST
Node root;
// Constructor
BinarySearchTree()
{
root = null;
}
// Inorder traversal of the tree
void inorder()
{
inorderUtil(this.root);
}
// Utility function for inorder traversal of the tree
void inorderUtil(Node node)
{
if (node == null)
return;
inorderUtil(node.left);
System.out.print(node.data + " ");
inorderUtil(node.right);
}
// This method mainly calls insertRec()
void insert(int key)
{
root = insertRec(root, key);
}
/* A recursive function to insert a new key in BST */
Node insertRec(Node root, int data)
{
/* If the tree is empty, return a new node */
if (root == null) {
root = new Node(data);
return root;
}
/* Otherwise, recur down the tree */
if (data < root.data)
root.left = insertRec(root.left, data);
else if (data > root.data)
root.right = insertRec(root.right, data);
return root;
}
// Method that adds values of given BST into ArrayList
// and hence returns the ArrayList
ArrayList treeToList(Node node, ArrayList
list)
{
// Base Case
if (node == null)
return list;
treeToList(node.left, list);
list.add(node.data);
treeToList(node.right, list);
return list;
}
// method that checks if there is a pair present
boolean isPairPresent(Node node, int target)
{
// This list a1 is passed as an argument
// in treeToList method
// which is later on filled by the values of BST
ArrayList a1 = new ArrayList<>();
// a2 list contains all the values of BST
// returned by treeToList method
ArrayList a2 = treeToList(node, a1);
int start = 0; // Starting index of a2
int end = a2.size() - 1; // Ending index of a2
while (start < end) {
if (a2.get(start) + a2.get(end) == target) // Target Found!
{
System.out.println("Pair Found: " + a2.get(start) + " + " + a2.get(end) + " "
+ "= " + target);
return true;
}
if (a2.get(start) + a2.get(end) > target) // decrements end
{
end--;
}
if (a2.get(start) + a2.get(end) < target) // increments start
{
start++;
}
}
System.out.println("No such values are found!");
return false;
}
// Driver function
public static void main(String[] args)
{
BinarySearchTree tree = new BinarySearchTree();
/*
15
/ \
10 20
/ \ / \
8 12 16 25 */
tree.insert(15);
tree.insert(10);
tree.insert(20);
tree.insert(8);
tree.insert(12);
tree.insert(16);
tree.insert(25);
tree.isPairPresent(tree.root, 33);
}
}
// This code is contributed by Kamal Rawal
C#
// C# code to find a pair with given sum
// in a Balanced BST
using System;
using System.Collections.Generic;
// A binary tree node
public class Node {
public int data;
public Node left, right;
public Node(int d)
{
data = d;
left = right = null;
}
}
public class BinarySearchTree {
// Root of BST
Node root;
// Constructor
BinarySearchTree()
{
root = null;
}
// Inorder traversal of the tree
void inorder()
{
inorderUtil(this.root);
}
// Utility function for inorder traversal of the tree
void inorderUtil(Node node)
{
if (node == null)
return;
inorderUtil(node.left);
Console.Write(node.data + " ");
inorderUtil(node.right);
}
// This method mainly calls insertRec()
void insert(int key)
{
root = insertRec(root, key);
}
/* A recursive function to insert a new key in BST */
Node insertRec(Node root, int data)
{
/* If the tree is empty, return a new node */
if (root == null) {
root = new Node(data);
return root;
}
/* Otherwise, recur down the tree */
if (data < root.data)
root.left = insertRec(root.left, data);
else if (data > root.data)
root.right = insertRec(root.right, data);
return root;
}
// Method that adds values of given BST into ArrayList
// and hence returns the ArrayList
List treeToList(Node node, List list)
{
// Base Case
if (node == null)
return list;
treeToList(node.left, list);
list.Add(node.data);
treeToList(node.right, list);
return list;
}
// method that checks if there is a pair present
bool isPairPresent(Node node, int target)
{
// This list a1 is passed as an argument
// in treeToList method
// which is later on filled by the values of BST
List a1 = new List();
// a2 list contains all the values of BST
// returned by treeToList method
List a2 = treeToList(node, a1);
int start = 0; // Starting index of a2
int end = a2.Count - 1; // Ending index of a2
while (start < end) {
if (a2[start] + a2[end] == target) // Target Found!
{
Console.WriteLine("Pair Found: " + a2[start] + " + " + a2[end] + " "
+ "= " + target);
return true;
}
if (a2[start] + a2[end] > target) // decrements end
{
end--;
}
if (a2[start] + a2[end] < target) // increments start
{
start++;
}
}
Console.WriteLine("No such values are found!");
return false;
}
// Driver code
public static void Main(String[] args)
{
BinarySearchTree tree = new BinarySearchTree();
/*
15
/ \
10 20
/ \ / \
8 12 16 25 */
tree.insert(15);
tree.insert(10);
tree.insert(20);
tree.insert(8);
tree.insert(12);
tree.insert(16);
tree.insert(25);
tree.isPairPresent(tree.root, 33);
}
}
// This code contributed by Rajput-Ji
C++
/* In a balanced binary search tree
isPairPresent two element which sums to
a given value time O(n) space O(logn) */
#include
using namespace std;
#define MAX_SIZE 100
// A BST node
class node {
public:
int val;
node *left, *right;
};
// Stack type
class Stack {
public:
int size;
int top;
node** array;
};
// A utility function to create a stack of given size
Stack* createStack(int size)
{
Stack* stack = new Stack();
stack->size = size;
stack->top = -1;
stack->array = new node*[(stack->size * sizeof(node*))];
return stack;
}
// BASIC OPERATIONS OF STACK
int isFull(Stack* stack)
{
return stack->top - 1 == stack->size;
}
int isEmpty(Stack* stack)
{
return stack->top == -1;
}
void push(Stack* stack, node* node)
{
if (isFull(stack))
return;
stack->array[++stack->top] = node;
}
node* pop(Stack* stack)
{
if (isEmpty(stack))
return NULL;
return stack->array[stack->top--];
}
// Returns true if a pair with target
// sum exists in BST, otherwise false
bool isPairPresent(node* root, int target)
{
// Create two stacks. s1 is used for
// normal inorder traversal and s2 is
// used for reverse inorder traversal
Stack* s1 = createStack(MAX_SIZE);
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;
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
// https:// www.geeksforgeeks.org/inorder-tree-traversal-without-recursion/
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) {
cout << "Pair Found: " << val1 << "+ " << val2 << " = " << target << endl;
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;
}
}
// A utility function to create BST node
node* NewNode(int val)
{
node* tmp = new node();
tmp->val = val;
tmp->right = tmp->left = NULL;
return tmp;
}
// Driver program to test above functions
int main()
{
/*
15
/ \
10 20
/ \ / \
8 12 16 25 */
node* root = NewNode(15);
root->left = NewNode(10);
root->right = NewNode(20);
root->left->left = NewNode(8);
root->left->right = NewNode(12);
root->right->left = NewNode(16);
root->right->right = NewNode(25);
int target = 33;
if (isPairPresent(root, target) == false)
cout << "\nNo such values are found\n";
return 0;
}
// This code is contributed by rathbhupendra
C
/* In a balanced binary search tree isPairPresent two element which sums to
a given value time O(n) space O(logn) */
#include
#include
#define MAX_SIZE 100
// A BST node
struct node {
int val;
struct node *left, *right;
};
// Stack type
struct Stack {
int size;
int top;
struct node** array;
};
// A utility function to create a stack of given size
struct Stack* createStack(int size)
{
struct Stack* stack = (struct Stack*)malloc(sizeof(struct Stack));
stack->size = size;
stack->top = -1;
stack->array = (struct node**)malloc(stack->size * sizeof(struct node*));
return stack;
}
// BASIC OPERATIONS OF STACK
int isFull(struct Stack* stack)
{
return stack->top - 1 == stack->size;
}
int isEmpty(struct Stack* stack)
{
return stack->top == -1;
}
void push(struct Stack* stack, struct node* node)
{
if (isFull(stack))
return;
stack->array[++stack->top] = node;
}
struct node* pop(struct Stack* stack)
{
if (isEmpty(stack))
return NULL;
return stack->array[stack->top--];
}
// 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
// https:// www.geeksforgeeks.org/inorder-tree-traversal-without-recursion/
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;
}
}
// A utility function to create BST node
struct node* NewNode(int val)
{
struct node* tmp = (struct node*)malloc(sizeof(struct node));
tmp->val = val;
tmp->right = tmp->left = NULL;
return tmp;
}
// Driver program to test above functions
int main()
{
/*
15
/ \
10 20
/ \ / \
8 12 16 25 */
struct node* root = NewNode(15);
root->left = NewNode(10);
root->right = NewNode(20);
root->left->left = NewNode(8);
root->left->right = NewNode(12);
root->right->left = NewNode(16);
root->right->right = NewNode(25);
int target = 33;
if (isPairPresent(root, target) == false)
printf("\n No such values are found\n");
getchar();
return 0;
}
Java
/* In a balanced binary search tree
isPairPresent two element which sums to
a given value time O(n) space O(logn) */
import java.util.*;
class GFG
{
static final int MAX_SIZE= 100;
// A BST node
static class node
{
int val;
node left, right;
};
// Stack type
static class Stack
{
int size;
int top;
node []array;
};
// A utility function to create a stack of given size
static Stack createStack(int size)
{
Stack stack = new Stack();
stack.size = size;
stack.top = -1;
stack.array = new node[stack.size];
return stack;
}
// BASIC OPERATIONS OF STACK
static int isFull(Stack stack)
{
return (stack.top - 1 == stack.size)?1:0 ;
}
static int isEmpty(Stack stack)
{
return stack.top == -1?1:0;
}
static void push(Stack stack, node node)
{
if (isFull(stack)==1)
return;
stack.array[++stack.top] = node;
}
static node pop(Stack stack)
{
if (isEmpty(stack) == 1)
return null;
return stack.array[stack.top--];
}
// Returns true if a pair with target
// sum exists in BST, otherwise false
static boolean isPairPresent(node root, int target)
{
// Create two stacks. s1 is used for
// normal inorder traversal and s2 is
// used for reverse inorder traversal
Stack s1 = createStack(MAX_SIZE);
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
boolean done1 = false, done2 = false;
int val1 = 0, val2 = 0;
node curr1 = root, curr2 = root;
// The loop will break when we either
// find a pair or one of the two
// traversals is complete
while (true)
{
// Find next node in normal Inorder
// traversal. See following post
// https:// www.geeksforgeeks.org/inorder-tree-traversal-without-recursion/
while (done1 == false)
{
if (curr1 != null)
{
push(s1, curr1);
curr1 = curr1.left;
}
else
{
if (isEmpty(s1) == 1)
done1 = true;
else
{
curr1 = pop(s1);
val1 = curr1.val;
curr1 = curr1.right;
done1 = true;
}
}
}
// 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) == 1)
done2 = true;
else {
curr2 = pop(s2);
val2 = curr2.val;
curr2 = curr2.left;
done2 = true;
}
}
}
// 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)
{
System.out.print("Pair Found: " +
val1+ "+ " +
val2+ " = " +
target +"\n");
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;
}
}
// A utility function to create BST node
static node NewNode(int val)
{
node tmp = new node();
tmp.val = val;
tmp.right = tmp.left = null;
return tmp;
}
// Driver program to test above functions
public static void main(String[] args)
{
/*
15
/ \
10 20
/ \ / \
8 12 16 25 */
node root = NewNode(15);
root.left = NewNode(10);
root.right = NewNode(20);
root.left.left = NewNode(8);
root.left.right = NewNode(12);
root.right.left = NewNode(16);
root.right.right = NewNode(25);
int target = 33;
if (isPairPresent(root, target) == false)
System.out.print("\nNo such values are found\n");
}
}
// This code is contributed by aashish1995
C#
/* In a balanced binary search tree
isPairPresent two element which sums to
a given value time O(n) space O(logn) */
using System;
using System.Collections.Generic;
public class GFG
{
static readonly int MAX_SIZE= 100;
// A BST node
public
class node
{
public
int val;
public
node left, right;
};
// Stack type
public
class Stack
{
public
int size;
public
int top;
public
node []array;
};
// A utility function to create a stack of given size
static Stack createStack(int size)
{
Stack stack = new Stack();
stack.size = size;
stack.top = -1;
stack.array = new node[stack.size];
return stack;
}
// BASIC OPERATIONS OF STACK
static int isFull(Stack stack)
{
return (stack.top - 1 == stack.size) ? 1 : 0 ;
}
static int isEmpty(Stack stack)
{
return stack.top == -1?1:0;
}
static void push(Stack stack, node node)
{
if (isFull(stack)==1)
return;
stack.array[++stack.top] = node;
}
static node pop(Stack stack)
{
if (isEmpty(stack) == 1)
return null;
return stack.array[stack.top--];
}
// Returns true if a pair with target
// sum exists in BST, otherwise false
static bool isPairPresent(node root, int target)
{
// Create two stacks. s1 is used for
// normal inorder traversal and s2 is
// used for reverse inorder traversal
Stack s1 = createStack(MAX_SIZE);
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;
node curr1 = root, curr2 = root;
// The loop will break when we either
// find a pair or one of the two
// traversals is complete
while (true)
{
// Find next node in normal Inorder
// traversal. See following post
// https:// www.geeksforgeeks.org/inorder-tree-traversal-without-recursion/
while (done1 == false)
{
if (curr1 != null)
{
push(s1, curr1);
curr1 = curr1.left;
}
else
{
if (isEmpty(s1) == 1)
done1 = true;
else
{
curr1 = pop(s1);
val1 = curr1.val;
curr1 = curr1.right;
done1 = true;
}
}
}
// 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) == 1)
done2 = true;
else {
curr2 = pop(s2);
val2 = curr2.val;
curr2 = curr2.left;
done2 = true;
}
}
}
// 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)
{
Console.Write("Pair Found: " +
val1+ "+ " +
val2+ " = " +
target +"\n");
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;
}
}
// A utility function to create BST node
static node NewNode(int val)
{
node tmp = new node();
tmp.val = val;
tmp.right = tmp.left = null;
return tmp;
}
// Driver program to test above functions
public static void Main(String[] args)
{
/*
15
/ \
10 20
/ \ / \
8 12 16 25 */
node root = NewNode(15);
root.left = NewNode(10);
root.right = NewNode(20);
root.left.left = NewNode(8);
root.left.right = NewNode(12);
root.right.left = NewNode(16);
root.right.right = NewNode(25);
int target = 33;
if (isPairPresent(root, target) == false)
Console.Write("\nNo such values are found\n");
}
}
// This code is contributed by aashish1995
输出 :
Pair Found: 8 + 25 = 33
- 复杂度分析:
- 时间复杂度: O(n)。
BST的有序遍历需要线性时间。 - 辅助空间: O(n)。
使用数组存储有序遍历。
- 时间复杂度: O(n)。
在上一篇文章中讨论了空间优化的解决方案。这个想法是首先将BST原地转换为双链表(DLL),然后在O(n)的时间内在排序的DLL中找到对。此解决方案需要O(n)时间和O(Logn)额外空间,但是会修改给定的BST。
下面讨论的解决方案占用O(n)时间,O(Logn)空间,并且不修改BST 。这个想法与在已排序的数组中查找对相同(有关详细信息,请参见此方法1)。我们同时以正常顺序和反向顺序遍历BST。相反,我们从最右边的节点开始,该节点是最大值节点。按照正常顺序,我们从最左侧的节点开始,该节点是最小值节点。我们在两个遍历中都加上当前节点的总和,然后将此总和与给定的目标总和进行比较。如果总和与目标总和相同,则返回true。如果总和大于目标总和,我们将以反向有序遍历的方式移至下一个节点,否则,我们以正常有序遍历的方式移至下一个节点。如果任何遍历都结束而没有找到对,则返回false。以下是此方法的C++实现。
C++
/* In a balanced binary search tree
isPairPresent two element which sums to
a given value time O(n) space O(logn) */
#include
using namespace std;
#define MAX_SIZE 100
// A BST node
class node {
public:
int val;
node *left, *right;
};
// Stack type
class Stack {
public:
int size;
int top;
node** array;
};
// A utility function to create a stack of given size
Stack* createStack(int size)
{
Stack* stack = new Stack();
stack->size = size;
stack->top = -1;
stack->array = new node*[(stack->size * sizeof(node*))];
return stack;
}
// BASIC OPERATIONS OF STACK
int isFull(Stack* stack)
{
return stack->top - 1 == stack->size;
}
int isEmpty(Stack* stack)
{
return stack->top == -1;
}
void push(Stack* stack, node* node)
{
if (isFull(stack))
return;
stack->array[++stack->top] = node;
}
node* pop(Stack* stack)
{
if (isEmpty(stack))
return NULL;
return stack->array[stack->top--];
}
// Returns true if a pair with target
// sum exists in BST, otherwise false
bool isPairPresent(node* root, int target)
{
// Create two stacks. s1 is used for
// normal inorder traversal and s2 is
// used for reverse inorder traversal
Stack* s1 = createStack(MAX_SIZE);
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;
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
// https:// www.geeksforgeeks.org/inorder-tree-traversal-without-recursion/
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) {
cout << "Pair Found: " << val1 << "+ " << val2 << " = " << target << endl;
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;
}
}
// A utility function to create BST node
node* NewNode(int val)
{
node* tmp = new node();
tmp->val = val;
tmp->right = tmp->left = NULL;
return tmp;
}
// Driver program to test above functions
int main()
{
/*
15
/ \
10 20
/ \ / \
8 12 16 25 */
node* root = NewNode(15);
root->left = NewNode(10);
root->right = NewNode(20);
root->left->left = NewNode(8);
root->left->right = NewNode(12);
root->right->left = NewNode(16);
root->right->right = NewNode(25);
int target = 33;
if (isPairPresent(root, target) == false)
cout << "\nNo such values are found\n";
return 0;
}
// This code is contributed by rathbhupendra
C
/* In a balanced binary search tree isPairPresent two element which sums to
a given value time O(n) space O(logn) */
#include
#include
#define MAX_SIZE 100
// A BST node
struct node {
int val;
struct node *left, *right;
};
// Stack type
struct Stack {
int size;
int top;
struct node** array;
};
// A utility function to create a stack of given size
struct Stack* createStack(int size)
{
struct Stack* stack = (struct Stack*)malloc(sizeof(struct Stack));
stack->size = size;
stack->top = -1;
stack->array = (struct node**)malloc(stack->size * sizeof(struct node*));
return stack;
}
// BASIC OPERATIONS OF STACK
int isFull(struct Stack* stack)
{
return stack->top - 1 == stack->size;
}
int isEmpty(struct Stack* stack)
{
return stack->top == -1;
}
void push(struct Stack* stack, struct node* node)
{
if (isFull(stack))
return;
stack->array[++stack->top] = node;
}
struct node* pop(struct Stack* stack)
{
if (isEmpty(stack))
return NULL;
return stack->array[stack->top--];
}
// 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
// https:// www.geeksforgeeks.org/inorder-tree-traversal-without-recursion/
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;
}
}
// A utility function to create BST node
struct node* NewNode(int val)
{
struct node* tmp = (struct node*)malloc(sizeof(struct node));
tmp->val = val;
tmp->right = tmp->left = NULL;
return tmp;
}
// Driver program to test above functions
int main()
{
/*
15
/ \
10 20
/ \ / \
8 12 16 25 */
struct node* root = NewNode(15);
root->left = NewNode(10);
root->right = NewNode(20);
root->left->left = NewNode(8);
root->left->right = NewNode(12);
root->right->left = NewNode(16);
root->right->right = NewNode(25);
int target = 33;
if (isPairPresent(root, target) == false)
printf("\n No such values are found\n");
getchar();
return 0;
}
Java
/* In a balanced binary search tree
isPairPresent two element which sums to
a given value time O(n) space O(logn) */
import java.util.*;
class GFG
{
static final int MAX_SIZE= 100;
// A BST node
static class node
{
int val;
node left, right;
};
// Stack type
static class Stack
{
int size;
int top;
node []array;
};
// A utility function to create a stack of given size
static Stack createStack(int size)
{
Stack stack = new Stack();
stack.size = size;
stack.top = -1;
stack.array = new node[stack.size];
return stack;
}
// BASIC OPERATIONS OF STACK
static int isFull(Stack stack)
{
return (stack.top - 1 == stack.size)?1:0 ;
}
static int isEmpty(Stack stack)
{
return stack.top == -1?1:0;
}
static void push(Stack stack, node node)
{
if (isFull(stack)==1)
return;
stack.array[++stack.top] = node;
}
static node pop(Stack stack)
{
if (isEmpty(stack) == 1)
return null;
return stack.array[stack.top--];
}
// Returns true if a pair with target
// sum exists in BST, otherwise false
static boolean isPairPresent(node root, int target)
{
// Create two stacks. s1 is used for
// normal inorder traversal and s2 is
// used for reverse inorder traversal
Stack s1 = createStack(MAX_SIZE);
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
boolean done1 = false, done2 = false;
int val1 = 0, val2 = 0;
node curr1 = root, curr2 = root;
// The loop will break when we either
// find a pair or one of the two
// traversals is complete
while (true)
{
// Find next node in normal Inorder
// traversal. See following post
// https:// www.geeksforgeeks.org/inorder-tree-traversal-without-recursion/
while (done1 == false)
{
if (curr1 != null)
{
push(s1, curr1);
curr1 = curr1.left;
}
else
{
if (isEmpty(s1) == 1)
done1 = true;
else
{
curr1 = pop(s1);
val1 = curr1.val;
curr1 = curr1.right;
done1 = true;
}
}
}
// 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) == 1)
done2 = true;
else {
curr2 = pop(s2);
val2 = curr2.val;
curr2 = curr2.left;
done2 = true;
}
}
}
// 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)
{
System.out.print("Pair Found: " +
val1+ "+ " +
val2+ " = " +
target +"\n");
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;
}
}
// A utility function to create BST node
static node NewNode(int val)
{
node tmp = new node();
tmp.val = val;
tmp.right = tmp.left = null;
return tmp;
}
// Driver program to test above functions
public static void main(String[] args)
{
/*
15
/ \
10 20
/ \ / \
8 12 16 25 */
node root = NewNode(15);
root.left = NewNode(10);
root.right = NewNode(20);
root.left.left = NewNode(8);
root.left.right = NewNode(12);
root.right.left = NewNode(16);
root.right.right = NewNode(25);
int target = 33;
if (isPairPresent(root, target) == false)
System.out.print("\nNo such values are found\n");
}
}
// This code is contributed by aashish1995
C#
/* In a balanced binary search tree
isPairPresent two element which sums to
a given value time O(n) space O(logn) */
using System;
using System.Collections.Generic;
public class GFG
{
static readonly int MAX_SIZE= 100;
// A BST node
public
class node
{
public
int val;
public
node left, right;
};
// Stack type
public
class Stack
{
public
int size;
public
int top;
public
node []array;
};
// A utility function to create a stack of given size
static Stack createStack(int size)
{
Stack stack = new Stack();
stack.size = size;
stack.top = -1;
stack.array = new node[stack.size];
return stack;
}
// BASIC OPERATIONS OF STACK
static int isFull(Stack stack)
{
return (stack.top - 1 == stack.size) ? 1 : 0 ;
}
static int isEmpty(Stack stack)
{
return stack.top == -1?1:0;
}
static void push(Stack stack, node node)
{
if (isFull(stack)==1)
return;
stack.array[++stack.top] = node;
}
static node pop(Stack stack)
{
if (isEmpty(stack) == 1)
return null;
return stack.array[stack.top--];
}
// Returns true if a pair with target
// sum exists in BST, otherwise false
static bool isPairPresent(node root, int target)
{
// Create two stacks. s1 is used for
// normal inorder traversal and s2 is
// used for reverse inorder traversal
Stack s1 = createStack(MAX_SIZE);
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;
node curr1 = root, curr2 = root;
// The loop will break when we either
// find a pair or one of the two
// traversals is complete
while (true)
{
// Find next node in normal Inorder
// traversal. See following post
// https:// www.geeksforgeeks.org/inorder-tree-traversal-without-recursion/
while (done1 == false)
{
if (curr1 != null)
{
push(s1, curr1);
curr1 = curr1.left;
}
else
{
if (isEmpty(s1) == 1)
done1 = true;
else
{
curr1 = pop(s1);
val1 = curr1.val;
curr1 = curr1.right;
done1 = true;
}
}
}
// 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) == 1)
done2 = true;
else {
curr2 = pop(s2);
val2 = curr2.val;
curr2 = curr2.left;
done2 = true;
}
}
}
// 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)
{
Console.Write("Pair Found: " +
val1+ "+ " +
val2+ " = " +
target +"\n");
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;
}
}
// A utility function to create BST node
static node NewNode(int val)
{
node tmp = new node();
tmp.val = val;
tmp.right = tmp.left = null;
return tmp;
}
// Driver program to test above functions
public static void Main(String[] args)
{
/*
15
/ \
10 20
/ \ / \
8 12 16 25 */
node root = NewNode(15);
root.left = NewNode(10);
root.right = NewNode(20);
root.left.left = NewNode(8);
root.left.right = NewNode(12);
root.right.left = NewNode(16);
root.right.right = NewNode(25);
int target = 33;
if (isPairPresent(root, target) == false)
Console.Write("\nNo such values are found\n");
}
}
// This code is contributed by aashish1995
输出:
Pair Found: 8 + 25 = 33
- 复杂度分析:
- 时间复杂度: O(n)。
BST的有序遍历需要线性时间。 - 辅助空间: O(logn)。
堆栈一次保存对数N的值
- 时间复杂度: O(n)。