바위타는 두루미

4.8 첫번째 공통 조상 본문

Study/Interview준비

4.8 첫번째 공통 조상

DoRoMii 2019. 7. 29. 16:27
728x90

문제 

이진트리에서 노드 두 개가 주어졌을때 이 두 노드의 첫 번째 공통조상을 찾는 알고리즘을 설계하고 그 코드를 작성하라. 자료구조내에 추가로 노드를 저장해 두면 안된다. 반드시 이진탐색트리일 필요는 없다. 

 

해법

1. 부모노드에 대한 링크가 있는 경우

 - p와 q에서 시작해서 둘이 만날 때까지 위로 올라가면 된다. (교집합문제와 비슷한 방식)

 - p의 경로를 따라 올라가면서 q를 덮을 수 있는 노드인지 확인한다. 

   p의 부모의 본인이 아닌 다른쪽의 하위노드들을 검사하여 q가 있다면 그것이 첫번째 조상, 아니라면 그 위의 부모를 탐색하는 방식

 

2. 부모노드에 대한 링크가 없는 경우

 - p와 q가 어떤 노드로부터 둘다 오른쪽에 있다면 오른쪽으로 내려가서 공통 조상의 여부를 찾아야 한다. 더이상 같은 쪽에 있지 않다면 그 노드가 바로 공통조상이 될 것이다. 이 방식대로 구현한다면 O(N)시간으로 최적시간이 나오긴하지만, 반복연산이 있다. 왜냐하면 처음에 기주점으로부터 왼쪽에 n, 오른쪽에 n개 탐색을 하면 2n번의 탐색 후 오른쪽 또는 왼쪽으로 분기하여 다시 2n/2개의 노드에 대해 호출되고 그다음에는 2n/4 .. 그러다보면 결국 o(N) 시간이 걸리지만 반복적으로 탐색하는 부분을 줄일 수 있을 것 같다. 

 

- 반복적으로 탐색하는 것을 줄이기 위해서 

  > 루트의 하위 트리가 p(또는 q)를 포함하고 q(또는 p)를 포함하지 않으면 p(또는 q)를 반환.

  > p나 q가 루트의 하위트리 내에 없으면 null을 반환한다. 

  > 어느곳에도 해당사항이 없으면 p와 q의 공통조상을 반환한다. 

  이런식으로 한번의 탐색으로 이전 노드들에 대한 검색 결과를 거품처럼 띄워 올리는 방식으로 기본적인 로직은 첫번째와 차이가 없다. 

 

class result:
    def __init__(self, node, isAncestor):
        self.node = node
        self.isAncestor = isAncestor

def Solution(root, p, q):
    re = AncHelper(root, p, q)
    if re.isAncestor : return re.node
    else : return None

def AncHelper(root, p, q):
    if root is None :
        return None
    if root == p and root == q:
        return (p, True)

    rx = isAncestor(root.left, p, q)
    if rx.isAncestor :
        return rx
    ry = isAncestor(root.right, p, q)
    if ry.isAncestor :
        return ry
    if rx and ry:
        return result(root, True)
    elif root == p or root == q:
        isAncestor = rx is not None or ry is not None
        return result(root, isAncestor)
    else :
        return result(rx if rx is not None else ry , False)


위의 코드를 보면 result class를 생성한 것을 볼 수 있다. 이곳에는 node와 이 노드가 조상인지의 여부를 가지고 있다.

이 클레스는 두가지 문제를 해결해 줄 수 있다. 

1. p가 q의 자식 ( 또는 q가 p의 자식)인경우

2. p는 존재하지만 q는 존재하지 않는 경우 ( 또는 그반대의 경우)

이 두가지 경우를 구분해 내지 못한다. 

실제로 q가 p의 자식이라면 p를 반환하여 원하는 결과를 얻을 수 있겠지만, 자식인지를 확인하지 않고 그럴 것이라고 생각하고 반환해버리는 것이기 때문에 p는 존재하지만 q가 존재하지 않는 경우에도 p를 반환하여 원하지 않는 결과를 얻을 수 있다. 

따라서 IsAncestor 변수를 두어서 이것이 실제 조상인지에 대한 bool값이 필요했다. 

 

 

'Study > Interview준비' 카테고리의 다른 글

4.10 하위 트리 확인  (0) 2019.07.29
4.9 BTS 수열  (0) 2019.07.29
4.7 순서정하기  (0) 2019.07.28
4.6 후속자  (0) 2019.07.28
4.5 BST 검증  (0) 2019.07.28
Comments