오늘 문제는 이진 트리에 관한 문제입니다. 한 번 살펴볼까요?
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p
and q
as the lowest node in T
that has both p
and q
as descendants (where we allow a node to be a descendant of itself).”
Example 1:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output: 3
Explanation: The LCA of nodes 5 and 1 is 3.
Example 2:
Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output: 5
Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
Example 3:
Input: root = [1,2], p = 1, q = 2
Output: 1
Constraints:
[2, 105]
.$-10^9$ <= Node.val <= $10^9$
Node.val
are unique.p != q
p
and q
will exist in the tree.Binary 트리 하나와 해당 트리에 속한 두 개의 노드가 주어집니다. 이 때, 두 노드의 공통 조상중 가장 낮은 node 즉, the lowest common ancestor (LCA)를 찾는 문제입니다.
트리 문제는 보통 트리 구현이나 트리 순회를 활용하는 문제 유형으로 나뉩니다. 따라서 의 시간복잡도가 나올것으로 예상됩니다.
첫번째 예시를 살펴보겠습니다.
p = 5, q = 1입니다.
공통 조상은 3인것을 알 수 있습니다.
두 번째 예시를 살펴보겠습니다.
p = 5, q = 4입니다.
LCA는 5입니다.
또 다른 예시를 보겠습니다.
p = 6, q = 7, LCA = 5입니다.
이와 같이 여러 예시를 통해 공통 조상을 찾는 문제의 핵심 아이디어를 파악할 수 있습니다.
LCA를 찾기 위해 루트에서 자식 노드로 내려가며 탐색해야 합니다. 이 과정에서 자식 노드 중 하나라도 p
또는 q
를 포함하면 해당 노드가 LCA 후보가 됩니다. 이를 통해 다음의 조건을 도출할 수 있습니다:
p
와 q
중 하나씩 발견되면 현재 노드가 공통 조상(LCA)입니다.p
나 q
중 하나일 경우, 해당 노드를 그대로 반환합니다. 자식 노드에 p
또는 q
가 없는 경우 LCA가 아닙니다.p
또는 q
를 찾은 경우에는 그 자식을 반환합니다. 이는 그 자식이 최종 LCA라는 뜻입니다.트리 순회를 통해 위의 조건을 효율적으로 확인할 수 있습니다. 후위 순회(DFS) 방식으로 트리를 탐색하며 조건을 검사하면 됩니다.
p
와 q
를 찾습니다.p
또는 q
일 경우 해당 노드를 반환합니다.p
와 q
의 가장 낮은 공통 조상이 됩니다.이 접근 방식으로 문제를 해결하면 시간 복잡도는 O(n)
이 될 것으로 예상되며, 각 노드를 한 번씩만 방문하게 됩니다.
# Definition for a binary tree node.
class TreeNode(object):
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
if root is None:
return None
left = self.lowestCommonAncestor(root.left,p,q)
right = self.lowestCommonAncestor(root.right,p,q)
if root.val == p.val or root.val == q.val:
return root
elif left and right:
return root
return left or right
코드 설명:
위의 코드는 재귀적으로 트리를 탐색하여 두 노드 p
와 q
의 가장 낮은 공통 조상(LCA)을 찾는 방식으로 작성되었습니다. 각 노드에서 다음과 같은 단계로 LCA를 탐색합니다:
None
이면 None
을 반환합니다.p
또는 q
인 경우: 현재 노드가 p
또는 q
와 일치하면 해당 노드를 반환합니다. 이는 현재 노드가 공통 조상의 후보가 될 수 있음을 의미합니다.lowestCommonAncestor
재귀 호출을 수행합니다.left
와 right
변수는 각각 왼쪽과 오른쪽에서 반환된 결과를 저장합니다.left
와 right
가 모두 None
이 아닌 경우, 즉, 두 자식 노드에서 각각 p
와 q
가 발견되었다면 현재 노드가 가장 낮은 공통 조상이므로, 현재 노드를 반환합니다.p
와 q
의 공통 조상(LCA)이 될 수 있습니다. 따라서 left
또는 right
값을 반환합니다.이 알고리즘은 깊이 우선 탐색(DFS)을 사용해 모든 노드를 한 번씩 방문하므로, 시간 복잡도는 O(n)
입니다. 이는 트리의 모든 노드를 탐색하면서 p
와 q
를 찾기 때문입니다.
시간 복잡도:
결과:
https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/submissions/1450309282
이번 문제에서는 이진 트리에서 두 노드의 가장 낮은 공통 조상을 찾는 방법을 다뤘습니다.
주요 포인트는 트리를 순회하며 각 노드의 자식 노드로 재귀 호출을 통해 p
와 q
가 존재하는 위치를 확인하는 것입니다. 이때, 현재 노드에서 왼쪽과 오른쪽 자식 노드로부터 각각 p
와 q
가 발견될 경우 그 노드가 바로 LCA임을 확정할 수 있습니다.
이 문제를 통해 다음과 같은 트리 탐색과 관련된 중요한 개념들을 복습할 수 있었습니다:
이러한 논리 구조는 다양한 트리 기반 문제에 적용할 수 있으며, 특히 트리의 특정 노드 간 관계를 파악해야 할 때 유용합니다.
읽어주셔서 감사합니다.
전체 코드는 다음 링크에서 확인할 수 있습니다. 이 코드에는 해당 문제를 3가지 예시를 돌리는 코드까지 나와있습니다.
오늘도 화이팅!!