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

파이썬으로 이진 트리의 최대 너비 구하기

이진 트리가 하나 주어졌을 때, 트리에서 가장 넓은 레벨의 최대 너비(maximum width)를 구하는 문제입니다. 여기서 레벨의 너비란 해당 레벨에서 가장 왼쪽에 있는 노드와 가장 오른쪽에 있는 노드 사이에 존재할 수 있는 노드의 개수를 의미합니다.

예를 들어 다음과 같은 이진 트리가 입력으로 주어지면,

파이썬으로 이진 트리의 최대 너비 구하기

출력 결과는 2가 됩니다.

해결 접근 방법

이 문제는 깊이 우선 탐색(DFS)위치 번호 매기기(position indexing)를 활용하면 효율적으로 해결할 수 있습니다. 각 노드에 힙(heap) 구조처럼 위치 번호를 부여하는 방식으로, 어떤 노드의 위치가 pos라면 왼쪽 자식은 2*pos, 오른쪽 자식은 2*pos+1이 됩니다.

이를 위해 다음과 같은 단계를 따릅니다.

  • 각 깊이별 최소 위치와 최대 위치를 저장할 맵(딕셔너리) d를 생성합니다. 최솟값은 무한대(infinity), 최댓값은 0으로 초기화합니다.
  • dfs() 함수를 정의합니다. 이 함수는 루트 노드, 위치 pos(기본값 0), 깊이 depth(기본값 0)를 매개변수로 받습니다.
  • 노드가 null이면 그대로 반환합니다.
  • d[depth][0]에는 기존 값과 현재 pos 중 더 작은 값을 저장합니다.
  • d[depth][1]에는 기존 값과 현재 pos 중 더 큰 값을 저장합니다.
  • 왼쪽 자식에 대해 dfs(node.left, 2*pos, depth+1)를 재귀 호출합니다.
  • 오른쪽 자식에 대해 dfs(node.right, 2*pos+1, depth+1)를 재귀 호출합니다.

메인 메소드에서는 아래와 같이 처리합니다.

  • dfs(root)를 호출하여 전체 트리를 순회합니다.
  • mx를 0으로 초기화합니다.
  • d에 저장된 모든 (최소, 최대) 쌍에 대해 left와 right를 구하고, mx를 max(mx, right-left+1)로 갱신합니다.
  • mx를 반환합니다.

구현 예제

from collections import defaultdict
   class TreeNode:
      def __init__(self, data, left = None, right = None):
         self.data = data
         self.left = left
         self.right = right
class Solution:
   def solve(self, root):
   d=defaultdict(lambda: [1e9,0])
   def dfs(node, pos=0, depth=0):
      if not node:
         return
      d[depth][0]=min(d[depth][0],pos)
      d[depth][1]=max(d[depth][1],pos)
      dfs(node.left,2*pos,depth+1)
      dfs(node.right,2*pos+1,depth+1)
   dfs(root)
   mx=0
   for interval in d.values():
      l,r=interval
      mx=max(mx,r-l+1)
   return mx

ob = Solution()
root = TreeNode(5)
root.left = TreeNode(1)
root.right = TreeNode(9)
root.right.left = TreeNode(7)
root.right.right = TreeNode(10)
root.right.left.left = TreeNode(6)
root.right.left.right = TreeNode(8)
print(ob.solve(root))

입력

root = TreeNode(5)
root.left = TreeNode(1)
root.right = TreeNode(9)
root.right.left = TreeNode(7)
root.right.right = TreeNode(10)
root.right.left.left = TreeNode(6)
root.right.left.right = TreeNode(8)

출력

2

복잡도 분석

시간 복잡도: O(n) — 트리의 모든 노드를 정확히 한 번씩 방문합니다.
공간 복잡도: O(n) — 재귀 호출 스택과 깊이별 위치 정보를 저장하는 맵이 추가로 필요합니다.