(백준) 가장 가까운 공통 조상 - 3584 [java]

2021. 8. 1. 23:32·알고리즘/백준

https://www.acmicpc.net/problem/3584

 

3584번: 가장 가까운 공통 조상

루트가 있는 트리(rooted tree)가 주어지고, 그 트리 상의 두 정점이 주어질 때 그들의 가장 가까운 공통 조상(Nearest Common Anscestor)은 다음과 같이 정의됩니다. 두 노드의 가장 가까운 공통 조상은, 두

www.acmicpc.net

 

🐢 설명

너무 어려운 트리문제를 맞닥뜨리고 충격을 먹고 골드 하위 문제 트리 문제를 풀려고 했다.

 

이 문제는 LCA 유형의 문제로 최단거리내 공통 조상을 찾는 문제이다.

 

문제접근은 먼저 인접리스트를 이용해서 부모 -> 자식의 단방향 그래프를 그리고, 추후 자식들이 부모를 찾아 올라가는 과정을 위해서 (자식 - 부모) 쌍의 map을 사용했다.

 

root에서 모든 자식들에 대한 트리 그래프가 완성되고 자식들이 자신의 부모를 알고나면 두개의 노드가 주어지는데 이들의 공통 부모를 찾아나서는 방식으로 접근했다.

 

1. root에서 각 노드들에 대한 높이를 구한다. 그 중 더 높이가 더 높은 (위치상 낮은) 노드를 찾아서 높이가 더 낮은 노드의 높이까지 맞춘다.

2. 높이를 맞춘 후에는 부모가 같아질 때까지 부모를 하나씩 같이 올린다.

 

다른풀이 (더 직관적이고 간단)

스터디를 같이하시는 분께서  푼 방법인데 훨씬 좋아보여서 적어본다.

 

트리를 부모 -> 자식관계로 구성하지 않고 역방향 (자식 -> 부모)관계로 그린다.

 

이 후 주어진 2개의 노드 각각에 대해서 Root 노드를 만날 때 까지 부모 노드를 탐색하면서 check한다. 두번째 탐색하는 노드에서 이미 check된 노드를 발견하면 해당 노드가 공통 노드이므로 바로 반환한다.

 

🐢코드 (내 풀이) (다른풀이는 적지 않는다)
package Gold이상문제_정리;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;

public class 가장가까운공통조상_3584 {
    static int T, N;
    static StringBuilder answer = new StringBuilder();
    static ArrayList<Integer>[] adj;
    static HashMap<Integer, Integer> chPaMap = new HashMap<>();
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        T = Integer.parseInt(br.readLine());

        while (T-- > 0) {
            N = Integer.parseInt(br.readLine());

            chPaMap.clear();
            boolean[] isNotRoot = new boolean[N+1];

            adj = new ArrayList[N + 1];
            for (int i = 0; i <= N; i++)
                adj[i] = new ArrayList<>();

            String[] input;
            for (int i = 0; i < N - 1; i++) {
                input = br.readLine().split(" ");
                int parent = Integer.parseInt(input[0]);
                int child = Integer.parseInt(input[1]);

                isNotRoot[child] = true;
                adj[parent].add(child);
                chPaMap.put(child, parent);
            }

            input = br.readLine().split(" ");
            int nodeA = Integer.parseInt(input[0]);
            int nodeB = Integer.parseInt(input[1]);
            int root = 1;
            while (isNotRoot[root]) root++;
            findCommonParent(root, nodeA, nodeB);
        }
        System.out.print(answer);
    }

    private static void findCommonParent(int root, int nodeA, int nodeB) {
        int heightA = findNode(root, nodeA, 0);
        int heightB = findNode(root, nodeB, 0);

        if (heightA < heightB)
            matching(nodeA, nodeB, heightA, heightB);
        else
            matching(nodeB, nodeA, heightB, heightA);
    }

    private static void matching(int topNode, int botNode, int topH, int botH) {
        while (botH > topH) {
            botH--;
            botNode = chPaMap.get(botNode);
        }

        while (topNode != botNode) {
            topNode = chPaMap.get(topNode);
            botNode = chPaMap.get(botNode);
        }
        answer.append(topNode).append("\n");
    }

    private static int findNode(int root, int node, int height) {
        if (root == node) return height;

        int h = 0;

        for (int next : adj[root]) {
            h += findNode(next, node, height + 1);
        }

        return h;
    }
}

 

🐢 마무리

알고리즘은 항상 더 쉽게 풀 수 있는 방법이 있는것 같다. 조금 더 문제를 천천히 쉽게 바라보는 시야를 가지기위해 노력하자.

반응형
저작자표시 (새창열림)

'알고리즘 > 백준' 카테고리의 다른 글

(백준) 13904 - 과제 [java]  (1) 2021.08.04
(백준) 13422 - 도둑 [java]  (0) 2021.08.04
(백준) 동전바꿔주기 - 2624 [java]  (1) 2021.08.01
(백준) 동전 - 9084 [java]  (1) 2021.08.01
(백준) 2225 - 합분해 [java]  (1) 2021.07.31
'알고리즘/백준' 카테고리의 다른 글
  • (백준) 13904 - 과제 [java]
  • (백준) 13422 - 도둑 [java]
  • (백준) 동전바꿔주기 - 2624 [java]
  • (백준) 동전 - 9084 [java]
구름뭉치
구름뭉치
구름의 개발일기장
  • 구름뭉치
    구름 개발일기장
    구름뭉치
  • 전체
    오늘
    어제
    • ALL (294)
      • 프로젝트 (23)
        • 토스페이먼츠 PG 연동 시리즈 (12)
        • JWT 방식 인증&인가 시리즈 (6)
        • 스우미 웹 애플리케이션 프로젝트 (1)
        • 스프링부트 기본 보일러 플레이트 구축 시리즈 (2)
        • 마이크로서비스 아키텍쳐 시리즈 (1)
      • 스프링 (43)
        • 스프링부트 API 설계 정리 (8)
        • 스프링부트 RestAPI 프로젝트 (18)
        • 스프링부트 WebSocket 적용기 (3)
        • 스프링 JPA 정리 시리즈 (5)
        • 스프링 MVC (5)
        • 스프링 배치 (2)
        • 토비의 스프링 정리 (2)
      • 기술 학습 (10)
        • 아파치 카프카 (9)
        • 클린 코드 (4)
        • 디자인 패턴의 아름다움 (2)
        • 모던 자바 인 액션 (7)
        • JVM 스레드 딥다이브 (7)
      • Web (25)
        • 정리글 (20)
        • GraphQL 정리글 (2)
        • Jenkins 정리글 (3)
      • 취업 (6)
      • CS (77)
        • 네트워크 전공 수업 정리 (11)
        • OSI 7계층 정리 (12)
        • 운영체제 정리 (19)
        • 데이터베이스 정리 (5)
        • MySql 정리 (17)
        • GoF의 Design Pattern 정리 (12)
      • 알고리즘 (70)
        • 백준 (56)
        • 프로그래머스 (12)
        • 알고리즘 정리본 (1)
      • 기초 지식 정리 (2)
      • 일상 (8)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    류블라냐
    마우스 패드
    레이저
    키보드 손목 받침대
    부다페스트
    mx master s3 for mac
    마우스
    크로아티아
    동유럽
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
구름뭉치
(백준) 가장 가까운 공통 조상 - 3584 [java]
상단으로

티스토리툴바