
- N개 대학교 이름이 주어질 때, N-1번의 합치기 연산
(i, j)를 순서대로 수행- s_i 뒤에 s_j를 이어 붙이고 s_j를 빈 문자열로 만든 뒤, 최종 이름을 출력하는 문제.
시도 1 - LinkedList<String>
시도 2 - ArrayList<StringBuilder>
list.get(i).append(list.get(j))로 문자열 직접 합치기최종 - next[] + tail[] 배열로 연결 리스트 구현
1. next[i]: i번 대학 다음에 연결된 대학 번호 (초기값 -1)
2. tail[i]: i번 체인의 마지막 노드 번호 (초기값 자기 자신 i)
3. 합치기 (i, j) 시:
next[tail[i]] = j → i 체인 끝에 j 체인 연결tail[i] = tail[j] → i 체인의 꼬리 갱신연결 리스트(Linked List)는 데이터를 저장할 때 하나의 데이터와 그 다음 데이터로의 위치를 함께 저장하여 논리적으로 연결(link)하는 방식으로 자료를 저장한다.
데이터는 논리적으로 연결되어 있으므로 배열과 달리 데이터의 삽입 삭제가 자유로워지면서 자연스럽게 전체 크기를 늘리고 줄이는 것 또한 가능해진다.

보통 node로 저장을 하고, 그 안에 데이터(data)와 다음 노드의 주소나 참조(next)를 담는다. 즉, node: data + next
Java에서는 LinkedList 클래스를 기본으로 제공한다.
import java.util.LinkedList;
LinkedList<String> list = new LinkedList<>();
// 삽입
list.add("A"); // 맨 뒤
list.addFirst("B"); // 맨 앞
list.addLast("C"); // 맨 뒤
// 조회
list.get(0); // 인덱스로 접근
list.getFirst(); // 첫 번째 요소
list.getLast(); // 마지막 요소
// 삭제
list.remove(0); // 인덱스로 삭제
list.removeFirst(); // 첫 번째 삭제
list.removeLast(); // 마지막 삭제
// 크기
list.size();
이중 연결 리스트(Doubly Linked List) 구조로 구현되어 있다. 심지어 List와 Deque 인터페이스를 모두 구현하므로, 리스트뿐 아니라 스택/큐/덱으로도 활용 가능하다.
tail[] 배열이 핵심: 리스트 끝을 항상 O(1)에 알 수 있어서 이어붙이기가 빠름import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
LinkedList<String> list = new LinkedList<>();
// 이 문제는 인덱스 1부터 시작
list.add("");
int N = Integer.parseInt(br.readLine());
for (int temp = 0; temp < N; temp++) list.add(br.readLine());
String s = "";
for (int temp = 0; temp < N-1; temp++) {
String[] nums = br.readLine().split(" ");
int i = Integer.parseInt(nums[0]);
int j = Integer.parseInt(nums[1]);
list.set(i, list.get(i) + list.get(j));
if (temp == N - 2) s = list.get(i);
}
System.out.println(s);
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
ArrayList<StringBuilder> list = new ArrayList<>();
// 이 문제는 인덱스 1부터 시작
list.add(new StringBuilder());
int N = Integer.parseInt(br.readLine());
for (int temp = 0; temp < N; temp++) list.add(new StringBuilder(br.readLine()));
int answer = 0;
for (int temp = 0; temp < N-1; temp++) {
String[] nums = br.readLine().split(" ");
int i = Integer.parseInt(nums[0]);
int j = Integer.parseInt(nums[1]);
list.get(i).append(list.get(j));
list.get(j).setLength(0);
answer = i;
}
System.out.println(list.get(answer));
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
String[] unis = new String[N + 1];
int[] next = new int[N + 1];
int[] tail = new int[N + 1];
for (int i = 1; i <= N; i++) {
unis[i] = br.readLine();
next[i] = -1;
tail[i] = i;
}
int answer = 0;
for (int temp = 0; temp < N - 1; temp++) {
String[] nums = br.readLine().split(" ");
int i = Integer.parseInt(nums[0]);
int j = Integer.parseInt(nums[1]);
next[tail[i]] = j;
tail[i] = tail[j];
answer = i;
}
StringBuilder sb = new StringBuilder();
int next_num = answer;
while (next_num != -1) {
sb.append(unis[next_num]);
next_num = next[next_num];
}
System.out.print(sb);
}
}
<초기 배열 상태>
unis: 0 1 2 3 4 5
next: -1 -1 -1 -1 -1 -1
tail: 0 1 2 3 4 5
<최종 배열 상태>
unis: 0 1 2 3 4 5
next: -1 2 3 4 5 -1
tail: 0 5 3 3 5 5
드디어 풀었다! 복병 해결
