📜  查找平衡BST中是否有一个三元组加到零

📅  最后修改于: 2021-05-25 00:33:59             🧑  作者: Mango

给定平衡二进制搜索树(BST),编写一个函数isTripletPresent(),如果给定BST中存在一个三元组且总和等于0,则该函数返回true,否则返回false。预期的时间复杂度为O(n ^ 2),并且只能使用O(Logn)多余的空间。您可以修改给定的二进制搜索树。请注意,平衡BST的高度始终为O(Logn)
例如,对于后面的BST,isTripletPresent()应该返回true,因为存在一个三元组,其总和为0,该三元组为{-13,6,7}。

蛮力解决方案是考虑BST中的每个三元组,并检查总和是否加到零。该解决方案的时间复杂度将为O(n ^ 3)。
更好的解决方案是创建一个辅助数组,并在该数组中存储BST的有序遍历。数组将被排序,因为BST的顺序遍历始终会产生排序的数据。一旦有了Inorder遍历,就可以使用本文的方法2来查找和等于0的三元组。此解决方案在O(n ^ 2)时间内有效,但需要O(n)辅助空间。
以下是在O(n ^ 2)时间内有效并且使用O(Logn)额外空间的解决方案
1)将给定的BST转换为双链表(DLL)
2)现在遍历DLL的每个节点,如果节点的密钥为负,则在DLL中找到一个对,其对等于当前节点的密钥乘以-1。为了找到这对,我们可以使用本文方法1中hasArrayTwoCandidates()中使用的方法。

C++
// A C++ program to check if there
// is a triplet with sum equal to 0 in
// a given BST
#include 
using namespace std;
 
// A BST node has key, and left and right pointers
class node
{
    public:
    int key;
    node *left;
    node *right;
};
 
// A function to convert given BST to Doubly
// Linked List. left pointer is used
// as previous pointer and right pointer
// is used as next pointer. The function
// sets *head to point to first and *tail
// to point to last node of converted DLL
void convertBSTtoDLL(node* root, node** head, node** tail)
{
    // Base case
    if (root == NULL)
        return;
 
    // First convert the left subtree
    if (root->left)
        convertBSTtoDLL(root->left, head, tail);
 
    // Then change left of current root
    // as last node of left subtree
    root->left = *tail;
 
    // If tail is not NULL, then set right
    // of tail as root, else current
    // node is head
    if (*tail)
        (*tail)->right = root;
    else
        *head = root;
 
    // Update tail
    *tail = root;
 
    // Finally, convert right subtree
    if (root->right)
        convertBSTtoDLL(root->right, head, tail);
}
 
// This function returns true if there
// is pair in DLL with sum equal to given
// sum. The algorithm is similar to hasArrayTwoCandidates()
// in method 1 of http://tinyurl.com/dy6palr
bool isPresentInDLL(node* head, node* tail, int sum)
{
    while (head != tail)
    {
        int curr = head->key + tail->key;
        if (curr == sum)
            return true;
        else if (curr > sum)
            tail = tail->left;
        else
            head = head->right;
    }
    return false;
}
 
// The main function that returns
// true if there is a 0 sum triplet in
// BST otherwise returns false
bool isTripletPresent(node *root)
{
    // Check if the given BST is empty
    if (root == NULL)
    return false;
 
    // Convert given BST to doubly linked list. head and tail store the
    // pointers to first and last nodes in DLLL
    node* head = NULL;
    node* tail = NULL;
    convertBSTtoDLL(root, &head, &tail);
 
    // Now iterate through every node and
    // find if there is a pair with sum
    // equal to -1 * heaf->key where head is current node
    while ((head->right != tail) && (head->key < 0))
    {
        // If there is a pair with sum
        // equal to -1*head->key, then return
        // true else move forward
        if (isPresentInDLL(head->right, tail, -1*head->key))
            return true;
        else
            head = head->right;
    }
 
    // If we reach here, then
    // there was no 0 sum triplet
    return false;
}
 
// A utility function to create
// a new BST node with key as given num
node* newNode(int num)
{
    node* temp = new node();
    temp->key = num;
    temp->left = temp->right = NULL;
    return temp;
}
 
// A utility function to insert a given key to BST
node* insert(node* root, int key)
{
    if (root == NULL)
    return newNode(key);
    if (root->key > key)
        root->left = insert(root->left, key);
    else
        root->right = insert(root->right, key);
    return root;
}
 
// Driver code
int main()
{
    node* root = NULL;
    root = insert(root, 6);
    root = insert(root, -13);
    root = insert(root, 14);
    root = insert(root, -8);
    root = insert(root, 15);
    root = insert(root, 13);
    root = insert(root, 7);
    if (isTripletPresent(root))
        cout << "Present";
    else
        cout << "Not Present";
    return 0;
}
 
// This code is contributed by rathbhupendra


C
// A C program to check if there is a triplet with sum equal to 0 in
// a given BST
#include
 
// A BST node has key, and left and right pointers
struct node
{
    int key;
    struct node *left;
    struct node *right;
};
 
// A function to convert given BST to Doubly Linked List. left pointer is used
// as previous pointer and right pointer is used as next pointer. The function
// sets *head to point to first and *tail to point to last node of converted DLL
void convertBSTtoDLL(node* root, node** head, node** tail)
{
    // Base case
    if (root == NULL)
        return;
 
    // First convert the left subtree
    if (root->left)
        convertBSTtoDLL(root->left, head, tail);
 
    // Then change left of current root as last node of left subtree
    root->left = *tail;
 
    // If tail is not NULL, then set right of tail as root, else current
    // node is head
    if (*tail)
        (*tail)->right = root;
    else
        *head = root;
 
    // Update tail
    *tail = root;
 
    // Finally, convert right subtree
    if (root->right)
        convertBSTtoDLL(root->right, head, tail);
}
 
// This function returns true if there is pair in DLL with sum equal
// to given sum. The algorithm is similar to hasArrayTwoCandidates()
// in method 1 of http://tinyurl.com/dy6palr
bool isPresentInDLL(node* head, node* tail, int sum)
{
    while (head != tail)
    {
        int curr = head->key + tail->key;
        if (curr == sum)
            return true;
        else if (curr > sum)
            tail = tail->left;
        else
            head = head->right;
    }
    return false;
}
 
// The main function that returns true if there is a 0 sum triplet in
// BST otherwise returns false
bool isTripletPresent(node *root)
{
    // Check if the given  BST is empty
    if (root == NULL)
       return false;
 
    // Convert given BST to doubly linked list.  head and tail store the
    // pointers to first and last nodes in DLLL
    node* head = NULL;
    node* tail = NULL;
    convertBSTtoDLL(root, &head, &tail);
 
    // Now iterate through every node and find if there is a pair with sum
    // equal to -1 * heaf->key where head is current node
    while ((head->right != tail) && (head->key < 0))
    {
        // If there is a pair with sum equal to  -1*head->key, then return
        // true else move forward
        if (isPresentInDLL(head->right, tail, -1*head->key))
            return true;
        else
            head = head->right;
    }
 
    // If we reach here, then there was no 0 sum triplet
    return false;
}
 
// A utility function to create a new BST node with key as given num
node* newNode(int num)
{
    node* temp = new node;
    temp->key = num;
    temp->left = temp->right = NULL;
    return temp;
}
 
// A utility function to insert a given key to BST
node* insert(node* root, int key)
{
    if (root == NULL)
       return newNode(key);
    if (root->key > key)
       root->left = insert(root->left, key);
    else
       root->right = insert(root->right, key);
    return root;
}
 
// Driver program to test above functions
int main()
{
    node* root = NULL;
    root = insert(root, 6);
    root = insert(root, -13);
    root = insert(root, 14);
    root = insert(root, -8);
    root = insert(root, 15);
    root = insert(root, 13);
    root = insert(root, 7);
    if (isTripletPresent(root))
        printf("Present");
    else
        printf("Not Present");
    return 0;
}


Java
// A Java program to check if there
// is a triplet with sum equal to 0 in
// a given BST
import java.util.*;
class GFG
{
 
  // A BST node has key, and left and right pointers
  static class node
  {
    int key;
    node left;
    node right;
  };
  static node head;
  static node tail;
 
  // A function to convert given BST to Doubly
  // Linked List. left pointer is used
  // as previous pointer and right pointer
  // is used as next pointer. The function
  // sets *head to point to first and *tail
  // to point to last node of converted DLL
  static void convertBSTtoDLL(node root)
  {
 
    // Base case
    if (root == null)
      return;
 
    // First convert the left subtree
    if (root.left != null)
      convertBSTtoDLL(root.left);
 
    // Then change left of current root
    // as last node of left subtree
    root.left = tail;
 
    // If tail is not null, then set right
    // of tail as root, else current
    // node is head
    if (tail != null)
      (tail).right = root;
    else
      head = root;
 
    // Update tail
    tail = root;
 
    // Finally, convert right subtree
    if (root.right != null)
      convertBSTtoDLL(root.right);
  }
 
  // This function returns true if there
  // is pair in DLL with sum equal to given
  // sum. The algorithm is similar to hasArrayTwoCandidates()
  // in method 1 of http://tinyurl.com/dy6palr
  static boolean isPresentInDLL(node head, node tail, int sum)
  {
    while (head != tail)
    {
      int curr = head.key + tail.key;
      if (curr == sum)
        return true;
      else if (curr > sum)
        tail = tail.left;
      else
        head = head.right;
    }
    return false;
  }
 
  // The main function that returns
  // true if there is a 0 sum triplet in
  // BST otherwise returns false
  static boolean isTripletPresent(node root)
  {
    // Check if the given BST is empty
    if (root == null)
      return false;
 
    // Convert given BST to doubly linked list. head and tail store the
    // pointers to first and last nodes in DLLL
    head = null;
    tail = null;
    convertBSTtoDLL(root);
 
    // Now iterate through every node and
    // find if there is a pair with sum
    // equal to -1 * heaf.key where head is current node
    while ((head.right != tail) && (head.key < 0))
    {
      // If there is a pair with sum
      // equal to -1*head.key, then return
      // true else move forward
      if (isPresentInDLL(head.right, tail, -1*head.key))
        return true;
      else
        head = head.right;
    }
 
    // If we reach here, then
    // there was no 0 sum triplet
    return false;
  }
 
  // A utility function to create
  // a new BST node with key as given num
  static node newNode(int num)
  {
    node temp = new node();
    temp.key = num;
    temp.left = temp.right = null;
    return temp;
  }
 
  // A utility function to insert a given key to BST
  static node insert(node root, int key)
  {
    if (root == null)
      return newNode(key);
    if (root.key > key)
      root.left = insert(root.left, key);
    else
      root.right = insert(root.right, key);
    return root;
  }
 
  // Driver code
  public static void main(String[] args)
  {
    node root = null;
    root = insert(root, 6);
    root = insert(root, -13);
    root = insert(root, 14);
    root = insert(root, -8);
    root = insert(root, 15);
    root = insert(root, 13);
    root = insert(root, 7);
    if (isTripletPresent(root))
      System.out.print("Present");
    else
      System.out.print("Not Present");
  }
}
 
// This code is contributed by aashish1995


C#
// A C# program to check if there
// is a triplet with sum equal to 0 in
// a given BST
using System;
public class GFG
{
 
  // A BST node has key, and left and right pointers
  public class node
  {
    public int key;
    public  node left;
    public  node right;
  };
  static node head;
  static node tail;
 
  // A function to convert given BST to Doubly
  // Linked List. left pointer is used
  // as previous pointer and right pointer
  // is used as next pointer. The function
  // sets *head to point to first and *tail
  // to point to last node of converted DLL
  static void convertBSTtoDLL(node root)
  {
 
    // Base case
    if (root == null)
      return;
 
    // First convert the left subtree
    if (root.left != null)
      convertBSTtoDLL(root.left);
 
    // Then change left of current root
    // as last node of left subtree
    root.left = tail;
 
    // If tail is not null, then set right
    // of tail as root, else current
    // node is head
    if (tail != null)
      (tail).right = root;
    else
      head = root;
 
    // Update tail
    tail = root;
 
    // Finally, convert right subtree
    if (root.right != null)
      convertBSTtoDLL(root.right);
  }
 
  // This function returns true if there
  // is pair in DLL with sum equal to given
  // sum. The algorithm is similar to hasArrayTwoCandidates()
  // in method 1 of http://tinyurl.com/dy6palr
  static bool isPresentInDLL(node head, node tail, int sum)
  {
    while (head != tail)
    {
      int curr = head.key + tail.key;
      if (curr == sum)
        return true;
      else if (curr > sum)
        tail = tail.left;
      else
        head = head.right;
    }
    return false;
  }
 
  // The main function that returns
  // true if there is a 0 sum triplet in
  // BST otherwise returns false
  static bool isTripletPresent(node root)
  {
 
    // Check if the given BST is empty
    if (root == null)
      return false;
 
    // Convert given BST to doubly linked list. head and tail store the
    // pointers to first and last nodes in DLLL
    head = null;
    tail = null;
    convertBSTtoDLL(root);
 
    // Now iterate through every node and
    // find if there is a pair with sum
    // equal to -1 * heaf.key where head is current node
    while ((head.right != tail) && (head.key < 0))
    {
      // If there is a pair with sum
      // equal to -1*head.key, then return
      // true else move forward
      if (isPresentInDLL(head.right, tail, -1*head.key))
        return true;
      else
        head = head.right;
    }
 
    // If we reach here, then
    // there was no 0 sum triplet
    return false;
  }
 
  // A utility function to create
  // a new BST node with key as given num
  static node newNode(int num)
  {
    node temp = new node();
    temp.key = num;
    temp.left = temp.right = null;
    return temp;
  }
 
  // A utility function to insert a given key to BST
  static node insert(node root, int key)
  {
    if (root == null)
      return newNode(key);
    if (root.key > key)
      root.left = insert(root.left, key);
    else
      root.right = insert(root.right, key);
    return root;
  }
 
  // Driver code
  public static void Main(String[] args)
  {
    node root = null;
    root = insert(root, 6);
    root = insert(root, -13);
    root = insert(root, 14);
    root = insert(root, -8);
    root = insert(root, 15);
    root = insert(root, 13);
    root = insert(root, 7);
    if (isTripletPresent(root))
      Console.Write("Present");
    else
      Console.Write("Not Present");
  }
}
 
// This code is contributed by aashish1995


输出:

Present