|
| 1 | +""" |
| 2 | +문제의 본질: "큰 트리 안에 작은 트리와 똑같은 부분이 있나?" |
| 3 | +
|
| 4 | +해결 아이디어: |
| 5 | +1. 큰 트리의 모든 위치를 하나씩 확인해보기 |
| 6 | +2. 각 위치에서 "여기서 시작하는 서브트리가 찾는 트리와 완전히 같은가?" 확인하기 |
| 7 | +
|
| 8 | +해결 방법: |
| 9 | +1. 큰 트리의 모든 노드를 순회 |
| 10 | +2. 각 노드에서 시작하는 서브트리가 찾는 트리와 같은지 확인 |
| 11 | +3. 같은 트리인지 확인하는 것은 별도 함수로 분리 |
| 12 | +
|
| 13 | +헤결에 필요한 두 개의 함수: |
| 14 | +1. isSubtree 함수 (메인 로직): "어디서 찾을 수 있나?" (탐색 담당) |
| 15 | + - root가 None이면 False 반환 (빈 트리에선 찾을 수 없음) |
| 16 | + - 현재 위치에서 완전히 같은 트리인지 확인 |
| 17 | + - 같지 않다면 왼쪽, 오른쪽 자식에서 재귀적으로 찾기 |
| 18 | +
|
| 19 | +2. isSameTree 함수 (보조 로직): "여기서 완전히 같나?" (비교 담당) |
| 20 | + - 두 트리가 완전히 같은지 확인 |
| 21 | + - 구조와 값이 모두 같아야 함 |
| 22 | + - 재귀적으로 모든 노드 비교 |
| 23 | +
|
| 24 | +왜 이렇게 풀까? |
| 25 | +- 서브트리는 어느 노드에서든 시작할 수 있음 |
| 26 | +- 따라서 모든 가능한 시작점을 확인해야 함 |
| 27 | +- 각 시작점에서 완전히 같은 트리인지 확인하면 됨 |
| 28 | +
|
| 29 | +기억하기 쉬운 방법: |
| 30 | +1. "모든 노드에서 시도해보기" (isSubtree) |
| 31 | +2. "완전히 같은지 확인하기" (isSameTree) |
| 32 | +이 두 가지 기능을 분리해서 생각하기! |
| 33 | +
|
| 34 | +시간복잡도: O(m × n) |
| 35 | +- m: root 트리의 노드 개수 |
| 36 | +- n: subRoot 트리의 노드 개수 |
| 37 | +- 최악의 경우 root의 모든 노드에서 subRoot와 비교 |
| 38 | +
|
| 39 | +공간복잡도: O(max(m, n)) |
| 40 | +- 재귀 호출 스택의 깊이는 트리의 높이와 같음 |
| 41 | +- 균형 트리라면 O(log n), 편향 트리라면 O(n) |
| 42 | +""" |
| 43 | + |
| 44 | + |
| 45 | +# 1. 먼저 TreeNode 클래스 정의 (이진 트리의 노드를 나타냄) |
| 46 | +class TreeNode: |
| 47 | + def __init__(self, val=0, left=None, right=None): |
| 48 | + self.val = val # 노드의 값 |
| 49 | + self.left = left # 왼쪽 자식 노드 |
| 50 | + self.right = right # 오른쪽 자식 노드 |
| 51 | + |
| 52 | + |
| 53 | +class Solution: |
| 54 | + # 2. 메인 함수: root 트리에서 subRoot와 같은 서브트리가 있는지 확인 |
| 55 | + def isSubtree(self, root, subRoot): |
| 56 | + |
| 57 | + # 기본 케이스 1: 큰 트리가 비어있으면 서브트리를 찾을 수 없음 |
| 58 | + if not root: |
| 59 | + return False |
| 60 | + |
| 61 | + # 기본 케이스 2: 현재 노드에서 서브트리와 완전히 일치하는지 확인 |
| 62 | + if self.isSameTree(root, subRoot): |
| 63 | + return True |
| 64 | + |
| 65 | + # 재귀 케이스: 왼쪽 서브트리 또는 오른쪽 서브트리에서 찾기 |
| 66 | + # 왼쪽 서브트리에서 찾거나 OR 오른쪽 서브트리에서 찾으면 True |
| 67 | + return (self.isSubtree(root.left, subRoot) or |
| 68 | + self.isSubtree(root.right, subRoot)) |
| 69 | + |
| 70 | + |
| 71 | + # 3. 보조 함수: 두 트리가 완전히 같은지 확인 (구조와 값 모두) |
| 72 | + def isSameTree(self, tree1, tree2): |
| 73 | + |
| 74 | + # 기본 케이스 1: 둘 다 비어있으면 같음 |
| 75 | + if not tree1 and not tree2: |
| 76 | + return True |
| 77 | + |
| 78 | + # 기본 케이스 2: 하나만 비어있으면 다름 |
| 79 | + if not tree1 or not tree2: |
| 80 | + return False |
| 81 | + |
| 82 | + # 기본 케이스 3: 현재 노드의 값이 다르면 다름 |
| 83 | + if tree1.val != tree2.val: |
| 84 | + return False |
| 85 | + |
| 86 | + # 재귀 케이스: 왼쪽 서브트리와 오른쪽 서브트리가 모두 같아야 함 |
| 87 | + # 왼쪽끼리 같고 AND 오른쪽끼리 같아야 전체가 같음 |
| 88 | + return (self.isSameTree(tree1.left, tree2.left) and |
| 89 | + self.isSameTree(tree1.right, tree2.right)) |
| 90 | + |
0 commit comments