백준 - 디스크 트리 (7432) : JAVA

이진원·2026년 2월 23일

문제 유형
트리, TreeMap, dfs

풀이 방법 도출
문제의 조건은 다음과 같습니다.

1. 갑자기 맥북이 상근이의 손에서 떨어졌고, 화면이 켜지지 않았다. AS센터에 문의해보니 수리비가 97만원이 나왔고, 상근이는 큰 혼란에 빠졌다. 돈도 중요하지만, 상근이는 그 속에 들어있는 파일이 걱정되기 시작했다. 다행히 상근이는 저장되어 있는 중요한 디렉토리의 전체 경로를 텍스트 파일로 따로 저장하고 있었다. 
2. 예를 들면, WINNT\SYSTEM32\CERTSRV\CERTCO~1\X86. 
상근이의 중요한 디렉토리의 전체 경로가 모두 주어졌을 때, 3. 디렉토리 구조를 구해 보기 좋게 출력하는 프로그램을 작성하시오.
4. 디렉토리 구조를 보기 좋게 출력한다. 한 줄에 하나씩 디렉토리의 이름을 출력하며, 공백은 디렉토리 구조상에서 깊이를 의미한다. 각 서브 디렉토리는 사전순으로 출력해야 하며, 부모 디렉토리에서 출력한 공백의 개수보다 1개 많게 공백을 출력한다. 

트리의 전체적인 이해만 있다면 쉽게 해결할 수 있는 문제입니다.

class Node {
	String key;
	int height;
	TreeMap<String, Node> children = new TreeMap<>((n1,n2)-> n1.compareTo(n2));
	
	Node(String key, int height) {
		this.key = key;
		this.height = height;
	}
}

평균 O(1)의 시간복잡도를 자식 노드를 탐색하고, 오름차순으로 트리를 출력하기 위해서 TreeMap에 자식 노드들을 저장합니다.

for (int i = 0; i < n; i++) {
    String path = br.readLine();

    String[] dir = path.split("\\\\");


    if (!tree.containsKey(dir[0])) {

        Node root = new Node(dir[0], 0);

        tree.put(dir[0], root);

        insert(root, dir, 1, dir.length);
    } else {

        Node root = tree.get(dir[0]);


        Node cur = findLeaf(root, dir, 1, dir.length);
        insert(cur, dir, cur.height + 1, dir.length);
    }
}

\는 escape 문자이기 때문에 \\\\\를 표현해야합니다.
첫 문자열이 root 노드의 키로 주어지기 때문에 이미 tree에 저장되어있는 키라면 findLeaf를 통해 리프 노드를 찾아 insert를 진행합니다.
이미 tree에 저장되어있는 키가 아니라면 처음부터 insert를 진행합니다.

static Node findLeaf(Node cur, String[] dir, int num, int len) {

    if (num >= len) {
        return cur;
    }

    String key = dir[num];

    if (cur.children.containsKey(key)) {
        return findLeaf(cur.children.get(key), dir, num + 1, len);
    } else {
        return cur;
    }
}

static void insert(Node cur, String[] dir, int num, int len) {

    if (num >= len) return;

    Node child = null;

    if (!cur.children.containsKey(dir[num])) {
        child = new Node(dir[num], num);
        cur.children.put(dir[num], child);
    } else {
        child = cur.children.get(dir[num]);
    }

    insert(child, dir, num + 1, len);


}

findLeafinsert 메서드는 위와 같습니다.

static void printTree(Node cur, StringBuilder sb) {

    for (int i = 0; i < cur.height; i++) sb.append(" ");
    sb.append(cur.key).append("\n");

    for (Map.Entry < String, Node > entry: cur.children.entrySet()) {
        printTree(entry.getValue(), sb);
    }


}

트리를 출력하는 것은 dfs를 사용했습니다.
전위순회의 특성을 갖기 때문입니다. (자식 -> 서브트리 순으로 출력)

시간 복잡도
O(N^2)

코드


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;


class Node {
	String key;
	int height;
	TreeMap<String, Node> children = new TreeMap<>((n1,n2)-> n1.compareTo(n2));
	
	Node(String key, int height) {
		this.key = key;
		this.height = height;
	}
}

public class Main {
	
	static TreeMap<String, Node> tree  = new TreeMap<>((n1,n2)-> n1.compareTo(n2));
	
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        int n = Integer.parseInt(st.nextToken());
        
        for (int i=0; i<n; i++) {
        	String path = br.readLine();
        	
        	String[] dir = path.split("\\\\");
        	
        	
        	if(!tree.containsKey(dir[0])) {
        		
        		Node root = new Node(dir[0], 0);
        		
        		tree.put(dir[0], root);
        		
        		insert(root, dir, 1, dir.length);
        	}
        	else {
        		
        		Node root = tree.get(dir[0]);
        		
        		
        		Node cur = findLeaf(root, dir, 1, dir.length);
        		insert(cur, dir, cur.height+1, dir.length);
        	}
        	
    
        }
        
        
        for (Map.Entry<String, Node> entry : tree.entrySet()) {
        	Node root = entry.getValue();
        	
        	StringBuilder sb = new StringBuilder();
        	printTree(root, sb);
        	sb.deleteCharAt(sb.length()-1);
        	System.out.println(sb.toString());
        }
        
       

    }
    
    static void printTree(Node cur, StringBuilder sb) {
    	
    	for (int i=0; i<cur.height; i++) sb.append(" ");
    	sb.append(cur.key).append("\n");
    	
    	for (Map.Entry<String, Node> entry : cur.children.entrySet()) {
    		printTree(entry.getValue(), sb);
		}
    	
    	
    }
    
    
    static Node findLeaf(Node cur, String[] dir, int num, int len) {
    	
    	if (num >= len) {
    		return cur;
    	}
    	
    	String key = dir[num];
    
    	if (cur.children.containsKey(key)) {
    		return findLeaf(cur.children.get(key), dir, num+1, len);
    	}
    	else {
    		return cur;
    	}
    }
    
    static void insert(Node cur, String[] dir, int num, int len) {
    	
    	if (num >= len) return;
    	
    	Node child = null;
    	
    	if (!cur.children.containsKey(dir[num])) {
    		child = new Node(dir[num], num);
    		cur.children.put(dir[num], child);
    	}
    	else  {
    		child = cur.children.get(dir[num]);
    	}
    	
    	insert(child, dir, num+1, len);
    	
    	
    }

}

0개의 댓글