Given the root of a binary tree, return the maximum width of the given tree.
The maximum width of a tree is the maximum width among all levels.
The width of one level is defined as the length between the end-nodes (the leftmost and rightmost non-null nodes), where the null nodes between the end-nodes that would be present in a complete binary tree extending down to that level are also counted into the length calculation.
It is guaranteed that the answer will in the range of a 32-bit signed integer.
Example 1:

Input: root = [1,3,2,5,3,null,9]
Output: 4
Explanation: The maximum width exists in the third level with length 4 (5,3,null,9).
Example 2:

Input: root = [1,3,2,5,null,null,9,6,null,7]
Output: 7
Explanation: The maximum width exists in the fourth level with length 7 (6,null,null,null,null,null,7).
Example 3:

Input: root = [1,3,2,5]
Output: 2
Explanation: The maximum width exists in the second level with length 2 (3,2).
출처 : https://leetcode.com/problems/maximum-width-of-binary-tree/description/
풀이
function widthOfBinaryTree(root: TreeNode | null): number {
let positions: number[] = [0];
let width: number = 0;
function dfs(node: TreeNode | null, level: number, position: number) {
if(!node) return;
if(positions[level] === undefined) positions.push(position);
let diff = position - positions[level];
width = Math.max(width, diff + 1);
dfs(node.left, level + 1, diff * 2);
dfs(node.right, level + 1, diff * 2 + 1);
}
dfs(root, 0, 0)
return width;
};
이진 트리의 최대 너비를 계산하는 함수
- positions: number[] = [0];
- 각 레벨에서 가장 왼쪽 노드의 위치를 저장하기 위한 배열. 초기 값은 0
- width: number = 0;
- 최대 너비를 저장하기 위한 변수. 초기 값은 0
- function dfs(node: TreeNode | null, level: number, position: number)
- DFS (깊이 우선 탐색)을 이용해 트리를 순회하는 재귀 함수.
- node는 현재 노드를 나타내며, null일 수 있다.
- level은 현재 노드의 레벨(깊이)
- position은 현재 노드의 위치를 나타냄
- if(!node) return;
- 현재 노드가 null인 경우, 재귀 호출을 종료
- if(positions[level] === undefined) positions.push(position);
- 현재 레벨의 가장 왼쪽 노드의 위치를 저장.만약 현재 레벨이 처음 등장하는 경우, 위치를 추가.
- let diff = position - positions[level];
- 현재 노드의 위치와 해당 레벨의 가장 왼쪽 노드의 위치의 차이를 계산.
- width = Math.max(width, diff + 1);
- 현재 레벨에서의 너비를 계산하고, 최대 너비를 업데이트
- dfs(node.left, level + 1, diff * 2);
- 왼쪽 자식 노드를 다음 레벨로 재귀 호출. 왼쪽 자식 노드의 위치는 diff * 2로 계산.
- dfs(node.right, level + 1, diff * 2 + 1);
- 오른쪽 자식 노드를 다음 레벨로 재귀 호출. 오른쪽 자식 노드의 위치는 diff * 2 + 1로 계산.
- dfs(root, 0, 0)
- 트리의 루트 노드에서 탐색을 시작. 초기 레벨은 0이고, 초기 위치는 0
- return width;
- 최대 너비를 반환
diff의 의미
diff는 현재 노드의 위치(position)와 해당 레벨에서 가장 왼쪽 노드의 위치(positions[level])의 차이
let diff = position - positions[level];
이 diff는 현재 노드가 해당 레벨의 가장 왼쪽 노드로부터 얼마나 떨어져 있는지를 나타냄
너비의 계산
이진 트리의 특정 레벨에서의 너비는 그 레벨에서 가장 왼쪽 노드부터 가장 오른쪽 노드까지의 거리에 해당.
예를 들어, 레벨 2의 노드 위치가 0, 1, 3이라면, 이 레벨의 너비는 가장 왼쪽 노드의 위치(0)와 가장 오른쪽 노드의 위치(3) 간의 거리,
즉 3 - 0 + 1 = 4
diff + 1의 의미
diff는 현재 노드의 위치와 가장 왼쪽 노드의 위치 차이이므로, diff + 1은 해당 레벨에서 현재 노드를 포함한 너비를 의미
1
/ \
3 2
/ \ \
5 3 9
트리 노드의 위치를 다음과 같이 정의:
- 루트 노드의 위치는 0.
- 각 노드의 왼쪽 자식의 위치는 부모의 위치 * 2.
- 각 노드의 오른쪽 자식의 위치는 부모의 위치 * 2 + 1.
이제 트리의 레벨별 노드 위치를 살펴보겠습니다:
- 레벨 0: [1] -> 위치: [0]
- 레벨 1: [3, 2] -> 위치: [0, 1]
- 레벨 2: [5, 3, 9] -> 위치: [0, 1, 3]
레벨 2에서 노드 5의 위치는 0, 노드 3의 위치는 1, 노드 9의 위치는 3
width 업데이트 과정
레벨 2에서:
- positions[level]은 0 (가장 왼쪽 노드의 위치)
- 노드 5의 diff = 0 - 0 = 0 -> 너비는 0 + 1 = 1
- 노드 3의 diff = 1 - 0 = 1 -> 너비는 1 + 1 = 2
- 노드 9의 diff = 3 - 0 = 3 -> 너비는 3 + 1 = 4
여기서 최종적으로 width는 4
예시
1
/ \
3 2
/ \ \
5 3 9
트리 노드의 위치를 다음과 같이 정의:
- 루트 노드의 위치는 0입니다.
- 각 노드의 왼쪽 자식의 위치는 부모의 위치 * 2.
- 각 노드의 오른쪽 자식의 위치는 부모의 위치 * 2 + 1.
코드 실행 과정
- 초기 상태:
- positions = [0] (루트 노드의 위치는 0으로 초기화)
- width = 0
- 루트 노드(1)에서 시작:
- dfs(1, 0, 0)
- 레벨 0에서 노드 1의 위치는 0
- positions = [0] (이미 초기화됨)
- diff = 0 - 0 = 0
- width = Math.max(0, 0 + 1) = 1
- 왼쪽 자식 노드(3)로 이동:
- dfs(3, 1, 0 * 2) = dfs(3, 1, 0)
- 레벨 1에서 노드 3의 위치는 0
- positions = [0, 0] (레벨 1의 첫 위치 0 추가)
- diff = 0 - 0 = 0
- width = Math.max(1, 0 + 1) = 1
- 왼쪽 자식 노드(5)로 이동:
- dfs(5, 2, 0 * 2) = dfs(5, 2, 0)
- 레벨 2에서 노드 5의 위치는 0
- positions = [0, 0, 0] (레벨 2의 첫 위치 0 추가)
- diff = 0 - 0 = 0
- width = Math.max(1, 0 + 1) = 1
- dfs(null, 3, 0 * 2) (왼쪽 자식 노드가 null이므로 반환)
- dfs(null, 3, 0 * 2 + 1) (오른쪽 자식 노드가 null이므로 반환)
- 오른쪽 자식 노드(3)로 이동:
- dfs(3, 2, 0 * 2 + 1) = dfs(3, 2, 1)
- 레벨 2에서 노드 3의 위치는 1
- diff = 1 - 0 = 1
- width = Math.max(1, 1 + 1) = 2
- dfs(null, 3, 1 * 2) (왼쪽 자식 노드가 null이므로 반환)
- dfs(null, 3, 1 * 2 + 1) (오른쪽 자식 노드가 null이므로 반환)
- 오른쪽 자식 노드(2)로 이동:
- dfs(2, 1, 0 * 2 + 1) = dfs(2, 1, 1)
- 레벨 1에서 노드 2의 위치는 1
- diff = 1 - 0 = 1
- width = Math.max(2, 1 + 1) = 2
- 오른쪽 자식 노드(9)로 이동:
- dfs(9, 2, 1 * 2 + 1) = dfs(9, 2, 3)
- 레벨 2에서 노드 9의 위치는 3
- diff = 3 - 0 = 3
- width = Math.max(2, 3 + 1) = 4
- dfs(null, 3, 3 * 2) (왼쪽 자식 노드가 null이므로 반환)
- dfs(null, 3, 3 * 2 + 1) (오른쪽 자식 노드가 null이므로 반환)
결론
이 과정을 통해 너비가 가장 넓은 레벨은 레벨 2이며, 최대 너비는 4.
이는 노드 5, 3, 9가 포함된 레벨에서 너비가 4임을 나타냄
'LeetCode' 카테고리의 다른 글
| 1834. Single-Threaded CPU / TypeScript (0) | 2024.07.02 |
|---|---|
| 640. Solve the Equation / TypeScript (1) | 2024.07.01 |
| 2349. Design a Number Container System / TypeScript (0) | 2024.06.23 |
| 1219. Path with Maximum Gold / TypeScript (0) | 2024.06.22 |
| 2248. Intersection of Multiple Arrays / TypeScript (0) | 2024.06.20 |