코딩테스트 연습 - 9주차

9 [[1,3],[2,3],[3,4],[4,5],[4,6],[4,7],[7,8],[7,9]] 3 7 [[1,2],[2,7],[3,7],[3,4],[4,5],[6,7]] 1

programmers.co.kr

 

 


 

 

 

  • 풀이

 

arraylist 배열을 사용해서 풀었습니다.

 

1. 모든 wires의 왼쪽 노드와 오른쪽 노드를 끊어가며 재귀를 통해 연결된 모든 노드의 개수를 계산해줍니다.

2. 왼쪽 노드와 오른쪽 노드의 차이의 절대값 중 가장 작은 값을 answer에 저장합니다.

 

 

  • 코드

 

import java.util.*;

class Solution {
    static ArrayList[] array;
    static boolean[] check;
    
    public int solution(int n, int[][] wires) {
        int answer = Integer.MAX_VALUE;
        array = new ArrayList[n+1];
        for(int i = 1 ; i <= n ; i++){
            array[i] = new ArrayList<Integer>();
        }
        
        for(int i = 0 ; i < wires.length; i++) {
            array[wires[i][0]].add(wires[i][1]);
            array[wires[i][1]].add(wires[i][0]);
        }
        
        for(int i = 0 ; i < wires.length; i++) {
            check = new boolean[n+1];
            check[wires[i][0]] = true;
            check[wires[i][1]] = true;
            int a = bfs(wires[i][0]);
            int b = bfs(wires[i][1]);
            answer = Math.min(answer, Math.abs(a-b));
        }
        
        return answer;
    }
    
    private static int bfs(int index) {
        int sum = 1;
        check[index] = true;
        for(int i = 0 ; i < array[index].size(); i++){
            if(check[(int)array[index].get(i)]) continue;
            sum += bfs((int)array[index].get(i));
        }
        
        return sum;
    }
}

 

 

코딩테스트 연습 - 입국심사

n명이 입국심사를 위해 줄을 서서 기다리고 있습니다. 각 입국심사대에 있는 심사관마다 심사하는데 걸리는 시간은 다릅니다. 처음에 모든 심사대는 비어있습니다. 한 심사대에서는 동시에 한

programmers.co.kr

 

 


 

  • 풀이

 

이분 탐색으로 풀었다.

 

이분 탐색은 start, end를 두고 mid값으로 target을 찾는 알고리즘이다.

 

이번 문제에서 mid는 걸리는 시간, target은 입국 심사를 기다리는 n명의 사람이다.

 

 

 

  • 코드

 

import java.util.*;

class Solution {
    public long solution(int n, int[] times) {
        long answer = Long.MAX_VALUE;
        Arrays.sort(times);
        
        long start = 0 , mid, end = Long.MAX_VALUE;
        while(start <= end){
            mid = (start + end) / 2;
            
            long sum = 0;
            for(int i=0; i<times.length; i++){
                sum += mid / times[i];
                
                if(sum >= n)
                    break;
            }
            
            if(n > sum){
                start = mid + 1;
            }
            else{
                end = mid - 1;
                answer = Math.min(answer, mid);
            }
        }
        
        return answer;
    }
}
 

코딩테스트 연습 - 섬 연결하기

4 [[0,1,1],[0,2,2],[1,2,5],[1,3,1],[2,3,8]] 4

programmers.co.kr

 

 

  • 풀이

최소 비용으로 모든 노드를 연결해야 하는 문제입니다.

 

최소 신장 트리 알고리즘인 크루스칼 알고리즘을 사용했습니다.

 

동작 과정

1. 비용이 적은 순으로 정렬을 합니다. (비용이 적은 순으로 먼저 연결해야 최소 비용으로 모든 노드를 가장 먼저 연결할 수 있다.)

2. parent 인덱스를 자신의 인덱스로 설정.

3. 우선순위 큐에 남아있는 cost가 가장 적은 노드먼저 연결을 시도합니다.

4. 부모 인덱스가 start와 end가 같다면 아무런 작업도 하지 않습니다.

5. 부모 인덱스가 다르다면 서로 연결이 되어있지 않기 때문에 연결을 해줍니다.

6. 위의 3~5를 반복합니다.

 

  • 코드

 

import java.util.*;

class Solution {
    static int[] parent;
    
    public int solution(int n, int[][] costs) {
        int answer = 0;
        parent = new int[n+1];
        PriorityQueue<Node> node = new PriorityQueue<>();
        for(int i = 0 ; i < costs.length; i++){
            node.add(new Node(costs[i][0], costs[i][1], costs[i][2]));
        }
        
        for(int i = 0 ; i < n ; i++) parent[i] = i;
        
        while(!node.isEmpty()) {
        	Node temp = node.poll();
        	
            if(find(temp.start) == find(temp.end)) continue;
            
            union(temp.start, temp.end);
            answer += temp.cost;    
            
        }
        
        return answer;
    }
    
    public int find(int n){
        if(parent[n] == n) return n;
        return parent[n] = find(parent[n]);
    }
    
    public void union(int a, int b){
        int rootA = find(a);
        int rootB = find(b);
        
       if(rootA != rootB) parent[rootB] = rootA;
    }
}

class Node implements Comparable<Node> {
    int start;
    int end;
    int cost;
    
    public Node(int start, int end, int cost) {
        this.start = start;
        this.end = end;
        this.cost = cost;
            
    }
    
    @Override
    public int compareTo(Node node){
        return this.cost - node.cost;
    }
}

 

2533번: 사회망 서비스(SNS)

첫 번째 줄에는 친구 관계 트리의 정점 개수 N이 주어진다. 단, 2 ≤ N ≤ 1,000,000이며, 각 정점은 1부터 N까지 일련번호로 표현된다. 두 번째 줄부터 N-1개의 줄에는 각 줄마다 친구 관계 트리의 에

www.acmicpc.net

 

 

 


 

 

  • 풀이

 

문제에는 두 명의 사람이 존재한다. 얼리 아답터인 사람얼리 아답터가 아닌 사람이다.

 

문제)

모든 사람이 아이디어를 퍼뜨리고 싶을 때 모든 사람에게 전파가 되어야한다. 

 

조건)

본인이 얼리 아답터가 아니라면 자신과 연결된 모든 사람은 얼리 아답터여야 아이디어를 받아들인다. (얼리 아답터인 사람 주변 사람이 얼리 아답터인 경우는 가능)

 

이는 2차원 DP를 이용해 풀어봤다.

dp[index][0] : 얼리 아답터가 아니다.

dp[index][1] : 얼리 아답터이다.

 

dp[index][0] += dp[nextIndex][1];
dp[index][1] += Math.min(dp[nextIndex][0], dp[nextIndex][1]);

이 부분이 핵심 코드이다.

 

dp[index][0]는 얼리 아답터가 아니기 때문에 모든 주변 사람은 얼리 아답터여야 한다. 따라서 dp[nextIndex][1]를 더해준다.
dp[index][1]는 얼리 아답터 이기 때문에 두변 사람은 얼리 아답터 or 얼리 아답터가 아니여도 된다. 따라서 dp[nextIndex][0]와 dp[nextIndex][1] 중에 더 작은 값을 더 해준다.

 

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	static int N, answer;
	static ArrayList<Integer>[] array;
	static int[][] dp;
	static boolean[] check;
	
	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(answer);
	}
	
	private static void SetData()throws Exception {
		InputReader in = new InputReader(System.in);

		N = in.nextInt();
		array = new ArrayList[N+1];
		check = new boolean[N+1];
		dp = new int[N+1][2];
		
		for(int i = 1; i <= N; i++)
			array[i] = new ArrayList<>();
		
		for(int i = 1; i < N; i++) {
			int a = in.nextInt();
			int b = in.nextInt();
			array[a].add(b);
			array[b].add(a);
		}
		
		dfs(1);
		answer = Math.min(dp[1][0], dp[1][1]);
    }
	
	private static void dfs(int index) {
		check[index] = true;
		dp[index][0] = 0;
		dp[index][1] = 1;
		
		for(int i = 0 ; i < array[index].size(); i++) {
			int nextIndex = array[index].get(i);
			if(check[nextIndex]) continue;
			
			dfs(nextIndex);
			dp[index][0] += dp[nextIndex][1];
			dp[index][1] += Math.min(dp[nextIndex][0], dp[nextIndex][1]);
		}
	}
}


class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

5430번: AC

각 테스트 케이스에 대해서, 입력으로 주어진 정수 배열에 함수를 수행한 결과를 출력한다. 만약, 에러가 발생한 경우에는 error를 출력한다.

www.acmicpc.net

 

 

 

 


 

 

 

 

  • 풀이

 

명령(R,D)와 숫자 배열이 있다.

R : front와 rear의 index가 뒤바뀜. front가 rear가되고 rear가 front가 됩니다.

D : 젤 앞인 front의 값을 remove시켜줍니다.

 

==>> dequeue에 최적화된 문제라고 생각했습니다. 이유는 dequeue의 경우 앞과 뒤 둘다 넣고 뺄 수 있기 때문입니다.

 

 

풀이 방식은 다음과 같습니다.

'D'의 명령이 있을 시 boolean변수를 통해 'R'의 명령이 들어올 시 앞을 빼야하는지 뒤를 빼야하는지 체크해줍니다.

'R'의 명령이 있을 시 체크한 boolean 변수를 통해 앞 or 뒤를 빼줍니다.

 

명령이 다 끝날시엔 체크한 boolean변수를 통해 앞에서부터 빼야하는지 뒤부터 빼야하는지 체크해 준 뒤 올바르게 빼주면서 출력합니다.

 

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	static StringBuilder sb;
	
	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(sb);
	}
	
	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		sb = new StringBuilder();
		int testcase = in.nextInt();
		
		while(testcase-- > 0) {
            char[] c = in.nextLine().toCharArray();
            int n = in.nextInt();

            String arrStr = in.nextLine();
            Deque<Integer> deque = new LinkedList<>();
            for (String s : arrStr.substring(1, arrStr.length() - 1).split(","))
                if (!s.equals(""))
                    deque.add(Integer.parseInt(s));

            sb.append(AC(deque, c)).append("\n");
		}
	}
	
    static String AC(Deque<Integer> deque, char[] c) {
        boolean reverse = false;

        for (char command : c) {
            if (command == 'R')
                reverse = !reverse;
            else {
                if (deque.size() == 0)
                    return "error";

                if (reverse)
                    deque.removeLast();
                else
                    deque.removeFirst();
            }
        }

        StringBuilder sb = new StringBuilder("[");
        while (!deque.isEmpty()) {
            sb.append(reverse ? deque.removeLast() : deque.removeFirst());
            if (deque.size() != 0)
                sb.append(',');
        }
        sb.append(']');

        return sb.toString();
    }
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

9177번: 단어 섞기

세 개의 단어가 주어졌을때, 꿍은 첫 번째 단어와 두 번째 단어를 섞어서 세 번째 단어를 만들 수 있는지 궁금해졌다. 첫 번째와 두 번째 단어는 마음대로 섞어도 되지만 원래의 순서는 섞여서는

www.acmicpc.net

 

 

 


 

 

 

  • 풀이

 

BFS방식을 사용했습니다.

 

처음엔 투포인터로 풀다가 cat, tree, catrtee의 경우 잘 해결되지 않는 점을 확인했습니다.

catrtee의 경우 첫번 째 t를 어디서 뽑아와야되는지 알 수 없습니다. 첫번째 단어 ca 뒤에 있는 t를 써도 되고, tree의 첫글자 t를 써도 됩니다. 따라서, 두 경우 다 확인해봐야 하니 BFS가 필요합니다.

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	static StringBuilder sb;
	static boolean[][] check;
	
	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(sb);
	}
    
	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

        sb = new StringBuilder();
        int testcase = in.nextInt();
        
        for(int i = 1 ; i <= testcase; i++) {
        	sb.append("Data set "+i+": ");
        	String[] temp = in.nextLine().split(" ");
        	check = new boolean[temp[1].length()+1][temp[2].length()+1];
        	
        	boolean check = CanMakeString(temp[0], temp[1], temp[2]);
        	
        	if(check)
        		sb.append("yes").append("\n");
        	else
        		sb.append("no").append("\n");
        }
        
	}
	
	private static boolean CanMakeString(String first, String second, String third) {
		Queue<int []> queue = new LinkedList<>();
		queue.add(new int[] {0, 0});
		check[0][0] = true;
		while (!queue.isEmpty()) {
			int[] index = queue.poll();

			if (index[0] + index[1] == third.length()) {
				return true;
			}

			if (index[0] < first.length() 
					&& first.charAt(index[0]) == third.charAt(index[0] + index[1]) 
					&& !check[index[0] + 1][index[1]]) {
				queue.add(new int[]{ index[0] + 1, index[1] });
				check[index[0] + 1][index[1]] = true;
			}
			if (index[1] < second.length() 
					&& second.charAt(index[1]) == third.charAt(index[0] + index[1])
					&& !check[index[0]][index[1] + 1]) {
				queue.add(new int[]{ index[0],index[1] + 1 });
				check[index[0]][index[1] + 1] = true;
			}
		}
		return false;
	}
}


class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

2866번: 문자열 잘라내기

첫 번째 줄에는 테이블의 행의 개수와 열의 개수인 R과 C가 주어진다. (2 ≤ R, C ≤ 1000) 이후 R줄에 걸쳐서 C개의 알파벳 소문자가 주어진다. 가장 처음에 주어지는 테이블에는 열을 읽어서 문자

www.acmicpc.net

 

 

 


 

 

  • 풀이

 

1. 이분탐색을 통해 열의 인덱스 (mid, end) 를 보내줍니다.

2. mid부터 end까지의 중복되는 문자열이 있는지 찾습니다.

3. 문자열이 있다면 right를 mid -1로 초기화 시키며 더 위의 열을 확인해줍니다.

4. 문자열이 없다면 left를 mid+1로 초기화 시키며 더 아래의 열을 확인해줍니다.

5. 2~4의 작업을 반복합니다.

 

위의 설명대로 구현하였으며, 같은 문자열이 있는지 check해줄 때의 데이터는 순서가 상관없으므로 더 빠른 HashSet을 이용했습니다.

 

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	static int R, C, answer;
	static char[][] array;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(answer);
	}

	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		R = in.nextInt();
		C = in.nextInt();
		array = new char[R][C];

		for (int i = 0; i < R; i++) {
			String s = in.nextLine();
			for (int j = 0; j < C; j++) {
				array[i][j] = s.charAt(j);
			}
		}

		binarySearch(1, R - 1, R - 1);
	}

	private static boolean check(int start, int end) {
		Set<String> s = new HashSet<>();

		for (int j = 0; j < C; j++) {
			String temp = "";
			for (int i = start; i <= end; i++)
				temp += array[i][j];

			if (!s.contains(temp))
				s.add(temp);
			else
				return false;
		}

		return true;
	}

	private static void binarySearch(int left, int right, int end) {
		while (left <= right) {

			int mid = (left + right) / 2;

			boolean flag = check(mid, end);

			if (flag) {
				if (answer < mid)
					answer = mid;
				left = mid + 1;
			} else {
				right = mid - 1;
			}
		}
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

 

 

  • 더 빠르고 메모리 적게 잡아먹는 다른 사람 코드

아래의 코드는 arrayList에 이미 모든 열로 이어진 행의 개수를 다 넣은 뒤 subString으로 더 빠르게 확인해 준 방법이다.

 

방법은 같지만 반복해서 Set에 데이터를 추가해주는 저의 코드에 비해 반복없이 1번만 작업해줌으로서 훨씬 시간을 단축해준 코드입니다. 

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main {

	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		int R = Integer.parseInt(st.nextToken());
		int C = Integer.parseInt(st.nextToken());
		char[][] arr = new char[R][C];

		for (int i = 0; i < R; i++) {
			arr[i] = br.readLine().toCharArray();
		}

		ArrayList<String> list = new ArrayList<>();
		StringBuilder sb = new StringBuilder("");
		for (int i = 0; i < C; i++) {
			sb.setLength(0);
			for (int j = 0; j < R; j++) {
				sb.append(arr[j][i]);
			}
			list.add(sb.toString());
		}

		int count = 0, start = 0, end = R;
		ArrayList<String> tempList = new ArrayList<>();
		while (start <= end) {
			tempList.clear();
			int mid = (start + end) / 2;
			for (int i = 0; i < list.size(); i++) {
				String temp = list.get(i);
				temp = temp.substring(mid, temp.length());
				if (!tempList.contains(temp)) {
					tempList.add(temp);
				} else {
					break;
				}
			}
			if (tempList.size() != list.size()) {
				end = mid - 1;
			} else {
				start = mid + 1;
				count = mid;
			}
		}
		System.out.print(count);
	}
}

 

14725번: 개미굴

첫 번째 줄은 로봇 개미가 각 층을 따라 내려오면서 알게 된 먹이의 정보 개수 N개가 주어진다.  (1 ≤ N ≤ 1000) 두 번째 줄부터 N+1 번째 줄까지, 각 줄의 시작은 로봇 개미 한마리가 보내준 먹이

www.acmicpc.net

 

 

 

 


 

  • 풀이

 

개미굴의 각 층을 표현하고 같은 층의 경우 사전순으로 먼저 출력되야 합니다.

 

TreeMap의 장점 중 하나는 자동으로 key값에 의해 자동 정렬 된다는 것입니다. (우선순위 큐와 비슷한 느낌)

 

저 같은 경우 Node라는 class를 만들어 현재 string과 자식 Treemap을 생성해 주었다.

 

 

맨 처음 연결시킬 string 입력이 올 시 now라는 Node를 만들어 준 뒤 root의 위치를 할당합니다. 그 후 입력된 String이 자식 Treemap의 키값 중 해당 String으로 된 TreeMap이 없다면 새롭게 자식 TreeMap을 만들어 연결 시켜줍니다. 그 후, now를 자식 node를 가리키게 합니다. (해당 동작은 자식 노드를 게속 연결시켜주기 위함.)

 

연결이 모두 다 되었다면, root에 연결된 자식 TreeMap을 하나씩 꺼내서 자식을 타고가면서 출력해주면 됩니다.

저는 재귀 형식으로 구현했습니다.

 

 

 


 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	static StringBuilder sb;
	
	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(sb);
	}
    
	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

        int n = in.nextInt();
        Trie trie = new Trie("");
        Trie node;
        sb = new StringBuilder();
        
        while(n-- > 0) {
        	String[] temp = in.nextLine().split(" ");
            int k = Integer.parseInt(temp[0]);
            node = trie;
            
            for(int j = 0 ; j < k ; j++) {
                String name = temp[j+1];
                
                if(!node.list.containsKey(name)) 
                    node.list.put(name, new Trie(name));
                
                node = node.list.get(name);
            }
        }
        
        print(trie, -1);
    }
    
    public static void print(Trie trie, int depth) {
        if(depth != -1) {
            for(int i = 0; i < depth; i++) {
                sb.append("--");
            }
            sb.append(trie.name).append("\n");
        }
        
        for(Trie tree : trie.list.values()) {
            print(tree, depth+1);
        }
    }
}

class Trie{
    TreeMap<String, Trie> list;
    String name;
    
    Trie(String name) {
        list = new TreeMap<>();
        this.name = name;
    }
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

+ Recent posts