限られた余分なスペースでXNUMXつのBSTをマージします


難易度 ハード
よく聞かれる Amazon (アマゾン) Google マイクロソフト PayU ユーバー
二分探索木 二分木

問題文

「限られた余分なスペースでXNUMXつのBSTをマージする」という問題は、XNUMXつ与えられることを示しています 二分探索木(BST)そして、両方のツリーの要素をソートされた順序で印刷する必要があります。 これは、要素が単一のBSTからのものであるように見える順序です。

入力

限られた余分なスペースでXNUMXつのBSTをマージします

出力

限られた余分なスペースでXNUMXつのBSTをマージします

4 5 6 7 9 13

説明:両方の入力ツリーをマージして形成された新しいツリーが画像に示されています。 結果のツリーを順番にトラバースすると、出力が得られます。

限られた余分なスペースでXNUMXつのBSTをマージするアプローチ

「限られた余分なスペースでXNUMXつのBSTをマージする」という問題は、マージされたツリーの順序どおりの走査を印刷するように要求します。 マージされたツリーは、指定されたXNUMXつのツリーをマージすることによって形成されます。 したがって、指定されたツリーをマージしようとします。 しかし、ツリーをマージする場合、これには多くのオーバーヘッドが必要です。 直接マージする代わりに、他の方法を考えることができます。 指定された両方のツリーのノードの値をソートされた形式で出力するだけでよいためです。

これを解決するために、両方のツリーで同時にバイナリ検索ツリーの反復順走査を実行しようとします。 これは、実行すると実行できます 順序トラバーサル。 そして、インオーダートラバーサルの両方のノードの値を比較します。 次に、XNUMXつのうち小さい方を出力し、大きい方のノードをスタック(反復的な順序トラバーサル中に使用されるスタック)にプッシュします。 いずれかのツリーを使い終わったら、ノードを残したまま、ツリー上で順番にトラバーサルを実行します。

コード

限られた余分なスペースでXNUMXつのBSTをマージするC ++コード

#include <bits/stdc++.h>
using namespace std;
struct node
{
    int data;
    node *left;
    node *right;
};

// returns a new node with supplied data
node* create(int data)
{
    node *temp = new node;
    temp->data = data;
    temp->left = temp->right = NULL;
    return temp;
}

void inorder(node *root)
{
    if(root){
        inorder(root->left);
        cout<<root->data<<" ";
        inorder(root->right);
    }
}

void merge(node *root1, node *root2)
{
    stack<node*> s1;node* cur1 = root1;
    stack<node*> s2;node* cur2 = root2;
    //if first tree is empty, print second tree
    if(!root1){
        inorder(root2);
        return;
    }
    // if second tree is empty, print first tree
    if(!root2){
        inorder(root2);
        return;
    }
    // print the nodes which are not yet visited or visited but not printed
    while(cur1 != NULL || !s1.empty() || cur2 != NULL || !s2.empty())
    {
        // iterative inorder
        if(cur1 != NULL || cur2 != NULL)
        {
            // Reach the leftmost node of both BSTs and push ancestors of
            // leftmost nodes to stack s1 and s2 respectively
            if(cur1 != NULL)
            {
                s1.push(cur1);
                cur1 = cur1->left;
            }
            if (cur2 != NULL)
            {
                s2.push(cur2);
                cur2 = cur2->left;
            }
        }
        else
        {
            // if anyone of the tree's current node becomes Null
            // then we need to check if stack is empty
            if(s1.empty())
            {
                while(!s2.empty())
                {
                    cur2 = s2.top();s2.pop();
                    cur2->left = NULL;
                    inorder(cur2);
                }
                return;
            }
            if(s2.empty())
            {
                while(!s1.empty())
                {
                    cur1 = s1.top();s1.pop();
                    cur1->left = NULL;
                    inorder(cur1);
                }
                return;
            }

            // compare elements at the top of both stacks
            cur1 = s1.top();s1.pop();
            cur2 = s2.top();s2.pop();

            // print the smaller of the two and push the larger element into the corresponding stack
            if(cur1->data < cur2->data)
            {
                cout<<cur1->data<<" ";
                cur1 = cur1->right;
                s2.push(cur2);
                cur2 = NULL;
            }
            else
            {
                cout<<cur2->data<<" ";
                cur2 = cur2->right;
                s1.push(cur1);
                cur1 = NULL;
            }
        }
    }
}

int main()
{
    node *root1 = NULL, *root2 = NULL;
    //first tree
    root1 = create(5);
    root1->left = create(4);
    root1->right = create(13);

    //second tree
    root2 = create(7);
    root2->left = create(6);
    root2->right = create(9);

    // Print sorted nodes of both trees
    merge(root1, root2);

    return 0;
}
4 5 6 7 9 13

限られた余分なスペースでXNUMXつのBSTをマージするJavaコード

import java.util.*;
import java.lang.*;
import java.io.*;
 
class node{
  int data;
  node left;
  node right;
}
 
class Tree{
  static node root;
  static int count;
  static node create(int data){
    node tmp = new node();
    tmp.data = data;
    tmp.left = null;
    tmp.right = null;
    return tmp;
  }
  
  static void inorder(node root)
  {
      if(root != null){
          inorder(root.left);
          System.out.print(root.data+" ");
          inorder(root.right);
      }
  }
  
  static void merge(node root1, node root2)
  {
      Stack<node> s1 = new Stack<>();node cur1 = root1;
      Stack<node> s2 = new Stack<>();node cur2 = root2;
      //if first tree is empty, print second tree
      if(root1 == null){
          inorder(root2);
          return;
      }
      // if second tree is empty, print first tree
      if(root2 == null){
          inorder(root1);
          return;
      }
      // print the nodes which are not yet visited or visited but not printed
      while(cur1 != null || s1.empty() == false || cur2 != null || s2.empty() == false)
      {
          if(cur1 != null || cur2 != null)
          {
              // Reach the leftmost node of both BSTs and push ancestors of
              // leftmost nodes to stack s1 and s2 respectively
              if(cur1 != null)
              {
                  s1.push(cur1);
                  cur1 = cur1.left;
              }
              if (cur2 != null)
              {
                  s2.push(cur2);
                  cur2 = cur2.left;
              }
          }
          else
          {
              // if anyone of the tree's current node becomes Null
              // then we need to check if stack is empty
              if(s1.empty() == true)
              {
                  while (s2.empty() == false)
                  {
                      cur2 = s2.pop();
                      cur2.left = null;
                      inorder(cur2);
                  }
                  return ;
              }
              if(s2.empty() == true)
              {
                  while (s1.empty() == false)
                  {
                      cur1 = s1.pop();
                      cur1.left = null;
                      inorder(cur1);
                  }
                  return ;
              }
  
              // compare elements at the top of both stacks
              cur1 = s1.pop();
              cur2 = s2.pop();
              
              // print the smaller of the two and push the larger element into the corresponding stack
              if (cur1.data < cur2.data)
              {
                  System.out.print(cur1.data+" ");
                  cur1 = cur1.right;
                  s2.push(cur2);
                  cur2 = null;
              }
              else
              {
                  System.out.print(cur2.data+" ");
                  cur2 = cur2.right;
                  s1.push(cur1);
                  cur1 = null;
              }
          }
      }
  }
  
  public static void main(String[] args)
  {
      node root1 = null;
      node root2 = null;
      //first tree
      root1 = create(5);
      root1.left = create(4);
      root1.right = create(13);
  
      //second tree
      root2 = create(7);
      root2.left = create(6);
      root2.right = create(9);
  
      // Print sorted nodes of both trees
      merge(root1, root2);
  }

}
4 5 6 7 9 13

複雑さの分析

時間の複雑さ

O(N + M)、 両方のツリーを同時に順番にトラバースしたためです。 順序どおりのトラバーサル中に、両方のツリーからノードを調べたため、時間計算量が線形になりました。

スペースの複雑さ

O(N + M)、 より正式には、スペースの複雑さは両方の木の高さの合計になります。 ただし、最悪の場合、入力が歪んだツリーになる可能性があり、その場合、高さはツリー内のノードの数に等しくなります。