"재귀도 당장은 음수의 개념처럼 직관적이지 않겠지만 꾸준히 학습하면 자연스럽게 직관이 생겨난다. 그것이 바로 우리가 꾸준히 공부하는 이유며, 알고리즘을 공부하는 이유다. 궁극적으로 더 좋은 코드를 작성할 수 있는 능력이다."


# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
if root:
root.left, root.right = \
self.invertTree(root.right), self.invertTree(root.left)
return root
return None
이 문제는 파이썬 다운 방식으로 정말 쉽게 풀 수 있다.
<재귀를 이용한 이진 트리 반전>

이 그림에서는 루트 노드인 4에서 시작하되, 지금까지와는 달리 여기서는 오른쪽부터 재귀 탐색을 진행한다.
self.invertTree의 파라미터로 root.right를 먼저 넘겼기 때문이다. 노드 9에서 첫 번째 스왑이 일어나고 (실제로는 그 자식인 None까지 탐색하다가 None을 리턴받은 이후에), 두 번째는 노드 6에서 스왑이 일어난다.
오른쪽 노드가 다 스왑된 이후에는 왼쪽 노드가 동일한 형태로 스왑된다.
마지막 7)번, 루트 노드 4의 자식 노드 간 최종 스왑이 이루어지기 직전의 상태는 다음과 같다. 
➕ 참고로 마지막 return None은 생략이 가능하다.
아무것도 리턴하지 않으면 자바나 C++은 당연히 에러를 내뱉겠지만 파이썬은 자연스럽게 None을 할당하기 때문이다.
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
if root:
root.left, root.right = \
self.invertTree(root.right), self.invertTree(root.left)
return root
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
queue = collections.deque([root])
while queue:
node = queue.popleft()
#부모 노드부터 하향식 스왑
if node:
node.left, node.right = node.right, node.left
queue.append(node.left)
queue.append(node.right)
return root
앞서 이진 트리의 최대 깊이 문제는 while구문 내부에 별도의 for문이 있어 부모 노드에 대해 따로 반복해야 했는데, 여기서는 그런 제약이 없어 자유롭게 스왑하면서 queue에 추가한다.
앞서 재귀 풀이가 가장 말단, 리프노드까지 내려가서 백트래킹하면서 스왑하는 상향(Bottom-Up) 방식이라면, 이 풀이는 부모 노드부터 스왑하면서 계속 아래로 내려가는 하향(Top-Down) 방식 풀이라 할 수 있다.
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
stack = collections.deque([root])
while stack:
node = stack.pop()
#부모 노드부터 하향식 스왑
if node:
node.left, node.right = node.right, node.left
stack.append(node.left)
stack.append(node.right)
return root
BFS로 탐색할 때는 popleft()로 처음 값을 추출했고, 여기서 DFS로 탐색할 때는 pop()으로 마지막 값을 추출했다.
변수명을 stack으로 바꾼건 다소 형식적이다.
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def invertTree(self, root: TreeNode) -> TreeNode:
stack = collections.deque([root])
while stack:
node = stack.pop()
#부모 노드부터 하향식 스왑
if node:
stack.append(node.left)
stack.append(node.right)
node.left, node.right = node.right, node.left #후위 순회
return root