Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python으로 이진 트리에서 가장 큰 이진 탐색 트리(BST) 하위 트리 찾기

문제 개요

하나의 이진 트리가 주어졌을 때, 그 안에서 노드 수가 가장 많은 하위 트리이진 탐색 트리(Binary Search Tree, BST)의 조건을 만족하는 것을 찾아야 합니다.

예를 들어 다음과 같은 입력 트리가 있다고 가정해 보겠습니다.

Python으로 이진 트리에서 가장 큰 이진 탐색 트리(BST) 하위 트리 찾기

이 경우 출력 결과는 다음과 같습니다.

Python으로 이진 트리에서 가장 큰 이진 탐색 트리(BST) 하위 트리 찾기

해결 접근 방법

이 문제는 후위 순회(post-order traversal)를 활용해 해결할 수 있습니다. 각 노드에 대해 왼쪽과 오른쪽 서브트리의 값을 모두 수집한 뒤, 해당 목록이 정렬되어 있는지 확인하면 그 하위 트리가 BST인지 판별할 수 있습니다.

구체적인 알고리즘은 다음과 같습니다.

  • max_size := [0], max_node := [null] 로 초기화합니다.
  • traverse(node) 함수를 정의합니다.
  • node가 null이면 빈 리스트를 반환합니다.
  • left := traverse(node.left), right := traverse(node.right) 를 재귀적으로 호출합니다.
  • lst := left + [node.val] + right 로 현재 노드를 포함한 전체 값 목록을 만듭니다.
  • lst가 오름차순으로 정렬되어 있다면 해당 하위 트리는 BST입니다. 이때 max_size보다 lst의 크기가 크면 max_size와 max_node를 갱신합니다.
  • lst를 반환하고, 루트에서 traverse(root)를 호출한 뒤 최종적으로 max_node[0]을 반환합니다.

Python 구현 예제

다음 코드를 통해 더 자세히 이해해 보겠습니다.

class TreeNode:
    def __init__(self, data, left=None, right=None):
        self.val = data
        self.left = left
        self.right = right

def print_tree(root):
    if root is not None:
        print_tree(root.left)
        print(root.val, end=', ')
        print_tree(root.right)

class Solution:
    def solve(self, root):
        max_size = [0]
        max_node = [None]

        def traverse(node):
            if not node:
                return []
            left = traverse(node.left)
            right = traverse(node.right)
            lst = left + [node.val] + right
            if sorted(lst) == lst:
                if max_size[0] < len(lst):
                    max_size[0] = len(lst)
                    max_node[0] = node
            return lst

        traverse(root)
        return max_node[0]

ob = Solution()
root = TreeNode(12)
root.left = TreeNode(3)
root.right = TreeNode(5)
root.right.left = TreeNode(4)
root.right.right = TreeNode(6)
print_tree(ob.solve(root))

입력

root = TreeNode(12)
root.left = TreeNode(3)
root.right = TreeNode(5)
root.right.left = TreeNode(4)
root.right.right = TreeNode(6)

출력

4, 5, 6,

동작 원리 설명

위 예제에서 루트 노드 12를 포함한 전체 트리는 BST 조건(왼쪽 자식 < 부모 < 오른쪽 자식)을 만족하지 않습니다. 반면 노드 5를 루트로 하는 하위 트리는 4 < 5 < 6 으로 BST 조건을 충족하며, 노드 3개로 구성된 가장 큰 BST 하위 트리입니다. 따라서 중위 순회 결과인 4, 5, 6,이 출력됩니다.

참고로 이 방식은 각 노드마다 리스트를 병합하고 정렬 여부를 검사하기 때문에 시간 복잡도는 O(n²)에 가깝습니다. 노드 수가 매우 많은 경우에는 각 서브트리마다 (최솟값, 최댓값, 노드 수, BST 여부) 정보를 함께 반환하는 최적화 기법(O(n))을 사용하는 것이 좋습니다.