[Quetion]
- 두 Binary Tree
p
와q
가 같은지 확인
두 binary tree가 같은 형태, 같은 값을 가지는지 확인하기 위해서는 모든 노드를 순회해야한다고 생각했고, DFS와 BFS 중 BFS의 방법으로 접근했다.
p
와 q
를 순회하며 노드의 값을 저장하고, 만약 트리의 형태가 다르면 (ex: p는 왼쪽 q는 오른쪽에 하위 트리가 구성 되어있는 경우) 순회 결과를 다르게 하기 위해 0을 추가로 삽입했다.
class Solution:
def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
# p와 q가 모두 None이거나 한쪽만 None일 경우
if p is None and q is None:
return True
if p is None or q is None:
return False
p_tree,q_tree=[],[]
self.level_search(p, p_tree)
self.level_search(q, q_tree)
return p_tree == q_tree
# BFS
def level_search(self, node, l):
queue = [(node, 0)]
while queue:
node, level = queue.pop(0)
if node is not None:
l.append(node.val)
if node.left:
queue.append((node.left, level+1))
if node.right:
queue.append((node.right, level+1))
else:
l.append(0)
Runtime: 32ms | Memory: 16.1MB
LeetCode 코드 중 Runtime 90%, Memory 94% 해당하는 결과
p
와q
트리를 각각 BFS로 순회모든 트리를 순회하고 마지막으로 두 리스트를 비교하기에 최악의 경우 O(N) 시간복잡도를 가지고, 방문한 노드의 값을 모두 저장해야하므로 O(N)의 공간복잡도를 가진다.
시간복잡도는 BFS, DFS 모두 모든 노드를 순회하기 때문에 O(N)으로서, 이미 최적화가 되었다고 생각하고 공간복잡도는 p_tree와 q_tree 리스트를 제거하는 방향으로 개선할 수 있을 것 같다.
# 개선 후
class Solution:
def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
if p is None and q is None:
return True
if p is None or q is None:
return False
queue = [(p, q)]
while queue:
np, nq = queue.pop(0)
if np is None and nq is None:
continue
elif np is None or nq is None or np.val != nq.val:
return False
queue.append((np.left, nq.left))
queue.append((np.right, nq.right))
return True
시간복잡도와 공간복잡도는 여전히 O(N)으로 변함이 없지만 두 리스트를 제거함으로써 메모리에 할당되는 것을 줄였다.
코드도 더 간단해졌지만 while문 내부의 조건문이 길어져서 가독성은 떨어질 수 있겠다고 생각했다.
메모리적으로 더 유리할 수 있지만 개인적으로 개선한 코드보다는 함수로 작성한 이전 로직이 보기에도 편하고, 비즈니스 로직이라고 생각했을 때, 유지보수성이 더 높을 것 같다고 판단된다.