Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++로 두 개의 BST에서 합이 x와 같은 노드 쌍 개수 구하기

두 개의 이진 탐색 트리(Binary Search Tree, BST)와 값 x가 입력으로 주어졌을 때, 각 트리에서 노드를 하나씩 선택하여 두 노드 값의 합이 x와 같아지는 쌍의 개수를 구하는 것이 목표입니다. 예를 들어 BST_1에서 노드 1을, BST_2에서 노드 2를 가져와 두 데이터 값을 더했을 때 그 합이 x라면 카운트를 1 증가시킵니다.

구체적인 예시를 통해 살펴보겠습니다.

입출력 예시

입력 

C++로 두 개의 BST에서 합이 x와 같은 노드 쌍 개수 구하기

출력 − 합이 x와 같은 두 BST의 노드 쌍 개수: 1

설명 − 해당하는 쌍은 (8, 6)입니다.

입력 

C++로 두 개의 BST에서 합이 x와 같은 노드 쌍 개수 구하기

출력 − 합이 x와 같은 두 BST의 노드 쌍 개수: 2

설명 − 해당하는 쌍은 (5, 15)와 (4, 16)입니다.

알고리즘 접근 방법

이 방법에서는 반복적 중위 순회(iterative inorder traversal) 기법을 사용하여 두 개의 BST를 순회합니다. BST 1은 가장 작은 노드부터 가장 큰 노드 방향으로 중위 순회를 진행하고, BST 2는 그 반대 방향으로 순회합니다. 그런 다음 두 BST의 현재 노드 값을 더한 뒤, 그 합이 x와 같으면 카운트를 증가시킵니다. 합이 x보다 크면 BST 2의 현재 노드를 중위 선행자(inorder predecessor)로 이동하고, 합이 x보다 작으면 BST 1의 현재 노드를 중위 후속자(inorder successor)로 이동합니다.

  • 정수 데이터와 왼쪽·오른쪽 자식 포인터를 가지는 두 개의 트리 BST_1과 BST_2를 준비합니다.

  • insert_node(int data) 함수는 새 데이터를 가진 노드를 트리에 삽입하고 해당 노드의 포인터를 반환합니다.

  • insert_node() 함수로 두 개의 BST를 생성한 뒤, BST_sum_x(Tree* BST_1, Tree* BST_2, int x)에 전달합니다.

  • BST_sum_x(Tree* BST_1, Tree* BST_2, int x) 함수는 두 트리의 루트 노드를 받아서, 데이터 합이 x가 되는 노드 쌍의 개수를 반환합니다.

  • 합이 x인 쌍의 개수를 저장할 count 변수를 0으로 초기화합니다.

  • 반복적 중위 순회를 위해 Tree* stack_top_1, *stack_top_2 두 개의 변수를 선언합니다.

  • 스택 두 개(stack_1, stack_2)를 생성합니다.

  • 바깥쪽 while 루프를 시작합니다.

  • while 루프를 사용해 BST_1의 가장 왼쪽(가장 작은) 노드까지 이동하면서 모든 노드를 stack_1에 push합니다.

  • while 루프를 사용해 BST_2의 가장 오른쪽(가장 큰) 노드까지 이동하면서 모든 노드를 stack_2에 push합니다.

  • 두 스택 중 하나라도 비어 있으면 바깥쪽 while 루프를 종료(break)합니다.

  • 두 스택의 최상단(top) 노드를 꺼내어 데이터 값을 더한 결과를 temp에 저장합니다.

  • temp(합) == x라면 count를 증가시키고, pop 연산으로 stack_1과 stack_2에서 각각 최상단 원소를 제거합니다.

  • BST_1 = stack_top_1->right, BST_2 = stack_top_2->left로 설정합니다(즉, BST_1에서는 다음 후속자로, BST_2에서는 다음 선행자로 이동).

  • temp < x라면 stack_1의 최상단만 제거하고 BST_1의 다음 후속자로 이동합니다.

  • temp > x라면 stack_2의 최상단만 제거하고 BST_2의 다음 선행자로 이동합니다.

  • 바깥쪽 while 루프가 끝나면, count에는 두 BST의 노드들 중 합이 x가 되는 쌍의 개수가 저장되어 있습니다.

  • 결과로 count를 반환합니다.

예제 코드

#include <bits/stdc++.h>
using namespace std;
struct Tree{
   int data;
   Tree* left, *right;
};
Tree* insert_node(int data){
   Tree* newNode = (Tree*)malloc(sizeof(Tree));
   newNode->data = data;
   newNode->left = NULL;
   newNode->right = NULL;
}
int BST_sum_x(Tree* BST_1, Tree* BST_2, int x){
   int count = 0;
   Tree* stack_top_1, *stack_top_2;
   stack<Tree*> stack_1, stack_2;
   if (BST_1 == NULL || BST_2 == NULL){
      return 0;
   }
   while (1){
      while (BST_1 != NULL){
         stack_1.push(BST_1);
         BST_1 = BST_1->left;
      }
      while (BST_2 != NULL){
         stack_2.push(BST_2);
         BST_2 = BST_2->right;
      }
      if (stack_1.empty() || stack_2.empty()){
         break;
      }
      stack_top_1 = stack_1.top();
      stack_top_2 = stack_2.top();
      int temp = stack_top_1->data + stack_top_2->data;
      if (temp == x){
         count++;
         stack_1.pop();
         stack_2.pop();
         BST_1 = stack_top_1->right;
         BST_2 = stack_top_2->left;
      }
      else if (temp < x){
         stack_1.pop();
         BST_1 = stack_top_1->right;
      }
      else{
         stack_2.pop();
         BST_2 = stack_top_2->left;
      }
   }
   return count;
}
int main(){
   // BST 1
   Tree* BST_1 = insert_node(15);
   BST_1->left = insert_node(10);
   BST_1->right = insert_node(8);
   BST_1->left->left = insert_node(12);
   BST_1->left->right = insert_node(24);
   BST_1->right->left = insert_node(16);
   // BST 2
   Tree* BST_2 = insert_node(20);
   BST_2->left = insert_node(16);
   BST_2->right = insert_node(4);
   BST_2->left->left = insert_node(18);
   BST_2->left->right = insert_node(28);
   BST_2->right->left = insert_node(22);
   int x = 28;
   cout<<"합이 x와 같은 두 BST의 노드 쌍 개수: "<<BST_sum_x(BST_1, BST_2, x);
   return 0;
}

실행 결과

위 코드를 실행하면 다음과 같은 출력이 생성됩니다.

합이 x와 같은 두 BST의 노드 쌍 개수: 1