코딩테스트

[프로그래머스 level2] 도넛과 막대 그래프 자바 DFS (Map, Set)

mhui123 2025. 4. 15. 09:53
반응형

https://school.programmers.co.kr/learn/courses/30/lessons/258711

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

문제

각 정점별로 번호가 주어져 있고, 도형은 도넛과 막대, 8자 3가지가 존재한다.

주어진 정점 목록 edges를 참조하여

최초 출발 정점과 각 도형의 갯수를 구하여라.

참고사항

edges : 정점들 [a,b] 형태이며, a번 정점에서 b번 정점으로 향하는 간선이 있다는 것을 나타냅니다.
도넛 : edge == node
막대 :  edge == node -1
8자 : else

접근

edges를 정리하고 생성된 정점을 찾는 부분부터 막힘

피드백

1. inDegree / outDegree 계산 : edges에서 node 의 in out 분리 및 카운트.
2. 생성된 정점 찾기
3. 생성된 정점의 각 자식 정점 → DFS/BFS로 구조물 분리 - visited[]로 이미 탐색한 정점 건너뛰기
4. 구조물 정점/간선 수 체크 → 도넛/막대/8자 판단
5. 최종 [생성된 정점, 도넛 수, 막대 수, 8자 수] 반환
public int[] solution(int[][] edges) {
        Map<Integer, Integer> outs = new HashMap<>();
        Map<Integer, Integer> ins = new HashMap<>();
        Set<Integer> nodes = new HashSet<>();

        //1. edge 정리
        for(int[] edge : edges){
            int start = edge[0];
            int end = edge[1];

            outs.put(start, outs.getOrDefault(start, 0) + 1);
            ins.put(end, ins.getOrDefault(end, 0) + 1);
            nodes.add(start);
            nodes.add(end);
        }

        //2.edges에서 생성된 정점 찾기. 진입이 0이면서 진출 2개 이상인 것 찾기.
        int createdNode = -1;
        for(int node : nodes){
            if(outs.getOrDefault(node, 0) >= 2 && ins.getOrDefault(node, 0) == 0){
                createdNode = node;
                break;
            }
        }

        //3. 생성된 정점에서 시작된 간선들 수집?
        Map<Integer, List<Integer>> graph = new HashMap<>();
        for(int[]edge : edges){
            graph.computeIfAbsent(edge[0], k-> new ArrayList<>()).add(edge[1]);
        }

        //4. 탐색
        int donut = 0, stick = 0, eight = 0;
        Set<Integer> visited = new HashSet<>();
        List<Integer> startNodes =graph.get(createdNode);
        if(startNodes != null){
            for(int next : startNodes){
                if(!visited.contains(next)){
                    int[] count = new int[]{0,0}; //nodes, edges
                    dfs(next, graph, visited, count);

                    int v = count[0], e = count[1];

                    if( e == v ) donut ++;
                    else if( e == v - 1) stick ++;
                    else eight ++;
                }
            }
        }


        return new int[]{createdNode, donut, stick, eight};
    }

    private void dfs(int node, Map<Integer,List<Integer>> graph, Set<Integer> visited, int[] count){
        visited.add(node);
        count[0] ++;
        if(graph.containsKey(node)){
            for(int next : graph.get(node)){
                count[1] ++;
                //미방문 체크
                if(!visited.contains(next)){
                    dfs(next,graph, visited, count);
                }
            }
        }
    }
반응형