- 자바 알고리즘/코테 문제를 풀 때 필요한 지식들을 실전에서 쓰는 것들만 정리했습니다.
- 세부 개념을 자세하게 설명하지 않습니다. 필요한 개념은 따로 공부하시길 권장드립니다.
입출력은 가장 기본이지만 처음엔 가장 어렵습니다.
class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 한 줄씩 입력받음
String str = br.readLine(); //
int i = Integer.parseInt(br.readLine()); // int는 Integer.parseInt()로 변환해줘야 함
}
}
class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 한 줄씩 입력받음
StringTokenizer st = new StringTokenizer(br.readLine()); // 토큰화해서 임시 저장
String str = st.nextToken(); // 공백 기준으로 잘라서 반환
}
}
가령 이렇게 입력이 주어지는 경우도 있습니다.
BBWB
BWBW
BBWB
WBBW
StringTokenizer를 떠올렸을 수도 있지만, 저렇게 공백없는 문자열로 주어졌을 때는 적용되지 않습니다. 이때는 간단하게 문자열로 받아서 charAt() 함수를 쓰면 됩니다.
class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 한 줄씩 입력받음
int N = Integer.parseInt(br.readLine());
int[][] board = new int[N][N];
for (int i = 0; i < N; i++) {
String line = br.readLine(); // 문자열 한 줄 받고
for (int j = 0; j < N; j++) {
board[i][j] = line.charAt(j); // 한 글자씩 저장
}
}
}
}
출력은 기본적으로
System.out.println()을 사용합니다.
System.out.print(): 출력 후 개행문자(\n) 없음System.out.println(): 출력 후 개행문자(\n) 있음하지만 System.out.print()은 여러 번 출력할 경우 시간이 오래 걸려 간혹 시간초과가 발생하기도 합니다.
그땐 StringBuilder에 임시 저장한 후 나중에 System.out.println()으로 한 번에 출력합니다.
class Main {
public static void main(String[] args) throws Exception {
StringBuilder sb = new StringBuilder();
int answer = 0;
sb.append(answer).append('\n'); // 개행문자도 append 해줘야 개행이 됨
System.out.println(sb.toString()); // .toString()은 생략해도 됨
}
}
StringBuilder 말고도 StringBuffer도 있습니다.
둘의 차이는 멀티스레드에서 thread-safe 하냐 안하냐 입니다.
StringBuilder는 멀티스레드에서 thread-safe 하지 않습니다. 즉, 동시성을 보장하지 않기 때문에 값이 공유되는 특징이 있습니다.
반면 StringBuffer는 멀티스레드에서 thread-safe 하기 때문에 그만큼 확인하는 시간이 늘어 StringBuilder보다 시간이 오래 걸립니다.
물론, 두 개 모두 System.out.println() 보다는 적게 걸리지만 어차피 알고리즘을 풀 때는 멀티스레드를 고려하지 않아도 되기 때문에 시간이 조금이라도 적게 걸리는 StringBuilder()를 쓰는게 이득입니다.
Java의 대표 자료구조로는
List,Set,Map이 있습니다. 해당 자료구조들은Collection을 상속받기 때문에Collection의 함수들도 속성으로 갖습니다.
Collection은Iterable을 상속받기 때문에iterator()을 사용할 수 있지만, 저는 개인적으로는 자주 사용하지 않습니다. (이터레이터 어려워욥 ㅜ)자주 사용하는 함수는 볼드체로 적었으니, 참고하세요.

가장 기본이 되는 자료구조입니다.
class Main {
public static void main(String[] args) throws Exception {
int[] arr = new int[10];
}
}
class Main {
public static void main(String[] args) throws Exception {
// 1차원 배열 채우기
int[] arr = new int[10];
Arrays.fill(arr, -1); // arr = { -1, -1, ... -1 }
// 2차원 배열 채우기
int[][] arr2 = new int[10][10];
for (int i = 0; i < 10; i++) {
Arrays.fill(arr2[i], -1); // arr = { { -1, -1, ... -1 }, ... , { -1, -1, ... -1 } }
}
}
}
class Main {
public static void main(String[] args) throws Exception {
int[] arr = { 1, 2, 3 };
int[] copy = Arrays.copyOf(arr, arr.length);
}
}
| 분류 | 함수 | 파라미터 | 설명 |
|---|---|---|---|
| 추가 | add(E e) | 추가할 원소 | 원소 하나 추가 |
| 전체 추가 | addAll(Collection<? extends E> c) | 추가할 컬렉션 | 컬렉션 전체 추가 |
| 포함 여부 | contains(Object o) | 찾을 원소 | 해당 원소가 있는지 |
| 전체 포함 여부 | containsAll(Collection<?> c) | 비교할 컬렉션 | 모든 원소를 포함하는지 |
| 동일 여부 | equals(Object o) | 비교 대상 | 컬렉션 내용이 같은지 |
| 비어있는지 | isEmpty() | - | 원소가 하나도 없는지 |
| 크기 | size() | - | 원소 개수 |
| 전체 삭제 | clear() | - | 모든 원소 삭제 |
| 삭제 | remove(Object o) | 삭제할 원소 | 해당 원소 삭제 |
| 전체 삭제 | removeAll(Collection<?> c) | 삭제할 컬렉션 | 컬렉션에 포함된 원소 전부 삭제 |
| 배열 변환 | toArray() | - | 배열로 변환 |
List의 제네릭 타입은 반드시 참조 타입(Reference Type) 이어야 합니다.
즉, int, long, double, char 같은 primitive type은 사용할 수 없습니다.
class Main {
public static void main(String[] args) throws Exception {
List<Integer> intList = new ArrayList<>();
List<Long> longList = new ArrayList<>();
List<Double> doubleList = new ArrayList<>();
List<Character> charList = new ArrayList<>();
List<Boolean> booleanList = new ArrayList<>();
List<String> stringList = new ArrayList<>();
List<int> list = new ArrayList<>(); // ❌ 컴파일 에러
List<long> list = new ArrayList<>(); // ❌
List<double> list = new ArrayList<>(); // ❌
list.add(1);
list.get(0);
list.set(0, 10);
list.remove(0);
list.size();
list.contains(10);
Collections.sort(list);
}
}
| 분류 | 함수 | 시간복잡도 | 파라미터 | 설명 |
|---|---|---|---|---|
| 추가 | add(E e) | 평균 O(1) | 추가할 원소 | 맨 뒤에 추가 |
| 위치 추가 | add(int index, E e) | O(N) | 인덱스, 원소 | 원하는 위치에 추가 |
| 전체 추가 | addAll(Collection<? extends E> c) | O(M) | 추가할 컬렉션 | 맨 뒤에 컬렉션 추가 |
| 위치 전체 추가 | addAll(int index, Collection<? extends E> c) | O(N + M) | 인덱스, 컬렉션 | 원하는 위치에 컬렉션 추가 |
| 조회 | get(int index) | O(1) | 인덱스 | 해당 위치 원소 반환 |
| 첫 번째 위치 | indexOf(Object o) | O(N) | 찾을 원소 | 처음 등장하는 인덱스 반환 |
| 마지막 위치 | lastIndexOf(Object o) | O(N) | 찾을 원소 | 마지막 등장하는 인덱스 반환 |
| 삭제(인덱스) | remove(int index) | O(N) | 인덱스 | 해당 위치 원소 삭제 후 반환 |
| 삭제(원소) | remove(Object o) | O(N) | 삭제할 원소 | 해당 원소 삭제 |
| 수정 | set(int index, E e) | O(1) | 인덱스, 원소 | 해당 위치 원소 변경 |
class Main {
public static void main(String[] args) throws Exception {
Set<Integer> set = new HashSet<>();
set.add(1);
set.remove(1);
set.contains(1);
set.size();
}
}
HashSet은 순서를 보장하지 않기 때문에 인덱스로 접근할 수 없습니다.
만약 특정 값을 꺼내고 싶다면 순회하거나 배열/리스트로 변환해야 합니다.
class Main {
public static void main(String[] args) throws Exception {
for (int num : set) {
System.out.println(num);
}
}
}
| 분류 | 함수 | 시간복잡도 | 파라미터 | 설명 |
|---|---|---|---|---|
| 추가 | add(E e) | 평균 O(1) | 추가할 원소 | 원소 추가 (중복이면 추가되지 않음) |
| 전체 추가 | addAll(Collection<? extends E> c) | O(M) | 추가할 컬렉션 | 컬렉션 전체 추가 |
| 포함 여부 | contains(Object o) | 평균 O(1) | 찾을 원소 | 해당 원소가 있는지 |
| 전체 포함 여부 | containsAll(Collection<?> c) | 평균 O(M) | 비교할 컬렉션 | 모든 원소를 포함하는지 |
| 삭제 | remove(Object o) | 평균 O(1) | 삭제할 원소 | 해당 원소 삭제 |
| 전체 삭제 | removeAll(Collection<?> c) | 평균 O(M) | 삭제할 컬렉션 | 컬렉션에 포함된 원소 전부 삭제 |
| 전체 삭제 | clear() | O(N) | - | 모든 원소 삭제 |
| 비어있는지 | isEmpty() | O(1) | - | 원소가 하나도 없는지 |
| 크기 | size() | O(1) | - | 원소 개수 |
| 배열 변환 | toArray() | O(N) | - | 배열로 변환 |
원소를 자동으로 정렬하여 저장하는 Set입니다.
HashSet은 순서를 보장하지 않지만, TreeSet은 항상 정렬된 순서를 유지합니다.
class Main {
public static void main(String[] args) throws Exception {
TreeSet<Integer> set = new TreeSet<>();
set.add(3);
set.add(1);
set.add(2);
System.out.println(set); // [1, 2, 3]
set.first(); // 최소값
set.last(); // 최대값
set.ceiling(4); // 4 이상인 최소 원소
set.floor(4); // 4 이하인 최대 원소
set.higher(4); // 4 초과인 최소 원소
set.lower(4); // 4 미만인 최대 원소
}
}
| 함수 | 설명 | 시간복잡도 |
|---|---|---|
add(E e) | 원소 추가 | O(log N) |
remove(Object o) | 원소 삭제 | O(log N) |
contains(Object o) | 포함 여부 확인 | O(log N) |
first() | 최소값 반환 | O(log N) |
last() | 최대값 반환 | O(log N) |
ceiling(E e) | e 이상인 최소 원소 반환 | O(log N) |
floor(E e) | e 이하인 최대 원소 반환 | O(log N) |
higher(E e) | e 초과인 최소 원소 반환 | O(log N) |
lower(E e) | e 미만인 최대 원소 반환 | O(log N) |
pollFirst() | 최소값 삭제 후 반환 | O(log N) |
pollLast() | 최대값 삭제 후 반환 | O(log N) |
isEmpty() | 원소가 비어있는지 확인 | O(1) |
size() | 원소 개수 | O(1) |
clear() | 모든 원소 삭제 | O(N) |
class Main {
public static void main(String[] args) throws Exception {
map.computeIfAbsent(2, k -> new ArrayList<>()).add("C");
map.put(1, "A");
map.get(1);
map.getOrDefault(0, "B");
map.remove(1);
map.containsKey(1);
map.containsValue("B");
// key 순회
for (String key : map.keySet()) {
}
// key-value 조합으로 순회
for (Map.Entry<String, Integer> entry : map.entrySet()) {
}
}
}
class Main {
public static void main(String[] args) throws Exception {
Map<K, List<V>> map = new HashMap<>();
if (!map.containsKey(key)) {
map.put(key, new ArrayList<>());
}
map.get(key).add(value);
// 한 줄로 하면 아래 코드
map.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
}
}
| 분류 | 함수 | 시간복잡도 | 파라미터 | 설명 |
|---|---|---|---|---|
| 추가/수정 | put(K key, V value) | 평균 O(1) | 키, 값 | 키에 값 저장 (기존 키면 덮어쓰기) |
| 전체 추가 | putAll(Map<? extends K, ? extends V> m) | 평균 O(M) | 추가할 Map | Map 전체 추가 |
| 조회 | get(Object key) | 평균 O(1) | 키 | 해당 키의 값 반환 |
| 기본값 조회 | getOrDefault(Object key, V defaultValue) | 평균 O(1) | 키, 기본값 | 키가 없으면 기본값 반환 |
| 포함 여부(Key) | containsKey(Object key) | 평균 O(1) | 키 | 해당 키가 있는지 |
| 포함 여부(Value) | containsValue(Object value) | O(N) | 값 | 해당 값이 있는지 |
| 삭제 | remove(Object key) | 평균 O(1) | 키 | 해당 키 삭제 |
| 삭제(Key, Value) | remove(Object key, Object value) | 평균 O(1) | 키, 값 | 키와 값이 모두 일치하면 삭제 |
| 전체 삭제 | clear() | O(N) | - | 모든 데이터 삭제 |
| 비어있는지 | isEmpty() | O(1) | - | 데이터가 없는지 |
| 크기 | size() | O(1) | - | Key-Value 개수 |
| Key 조회 | keySet() | O(1) | - | 모든 Key를 Set(View)으로 반환 |
| Value 조회 | values() | O(1) | - | 모든 Value를 Collection(View)으로 반환 |
| Entry 조회 | entrySet() | O(1) | - | 모든 Entry(Key-Value)를 Set(View)으로 반환 |
| 없으면 생성 | computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) | 평균 O(1) | 키, 생성 함수 | 키가 없으면 값을 생성 후 반환 |
양쪽에서 삽입과 삭제가 가능한 자료구조입니다.
Queue와Stack모두 구현할 수 있어서,Deque을 가장 많이 씁니다.
class Main {
public static void main(String[] args) throws Exception {
Deque<Integer> dq = new ArrayDeque<>();
dq.offer(1); // 큐처럼 사용
dq.poll(); // 큐처럼 사용
dq.push(2); // 스택처럼 사용
dq.pop(); // 스택처럼 사용
dq.peek();
dq.addFirst();
dq.addLast();
dq.pollFirst();
dq.pollLast();
dq.peekFirst();
dq.peekLast();
}
}
| 분류 | 함수 | 시간복잡도 | 파라미터 | 설명 |
|---|---|---|---|---|
| 앞 추가 | addFirst(E e) | O(1) | 추가할 원소 | 맨 앞에 원소 추가, 실패 시 예외 |
| 뒤 추가 | addLast(E e) | O(1) | 추가할 원소 | 맨 뒤에 원소 추가, 실패 시 예외 |
| 앞 추가 | offerFirst(E e) | O(1) | 추가할 원소 | 맨 앞에 원소 추가, 실패 시 false |
| 뒤 추가 | offerLast(E e) | O(1) | 추가할 원소 | 맨 뒤에 원소 추가, 실패 시 false |
| 앞 조회 | getFirst() | O(1) | - | 맨 앞 원소 반환, 비어 있으면 예외 |
| 뒤 조회 | getLast() | O(1) | - | 맨 뒤 원소 반환, 비어 있으면 예외 |
| 앞 조회 | peekFirst() | O(1) | - | 맨 앞 원소 반환, 비어 있으면 null |
| 뒤 조회 | peekLast() | O(1) | - | 맨 뒤 원소 반환, 비어 있으면 null |
| 앞 삭제 | removeFirst() | O(1) | - | 맨 앞 원소 삭제 후 반환, 비어 있으면 예외 |
| 뒤 삭제 | removeLast() | O(1) | - | 맨 뒤 원소 삭제 후 반환, 비어 있으면 예외 |
| 앞 삭제 | pollFirst() | O(1) | - | 맨 앞 원소 삭제 후 반환, 비어 있으면 null |
| 뒤 삭제 | pollLast() | O(1) | - | 맨 뒤 원소 삭제 후 반환, 비어 있으면 null |
| 원소 삭제 | removeFirstOccurrence(Object o) | O(N) | 삭제할 원소 | 앞에서부터 처음 일치하는 원소 삭제 |
| 원소 삭제 | removeLastOccurrence(Object o) | O(N) | 삭제할 원소 | 뒤에서부터 처음 일치하는 원소 삭제 |
| 포함 여부 | contains(Object o) | O(N) | 찾을 원소 | 해당 원소가 있는지 확인 |
| 전체 삭제 | clear() | O(N) | - | 모든 원소 삭제 |
| 비어 있는지 | isEmpty() | O(1) | - | 원소가 하나도 없는지 |
| 크기 | size() | O(1) | - | 원소 개수 |
우선순위큐는 자동으로 정렬되는 Queue입니다.
기본은 오름차순입니다.
class Main {
public static void main(String[] args) throws Exception {
// 기본(오름차순)
PriorityQueue<Integer> pq = new PriorityQueue<>();
// 내림차순
PriorityQueue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());
PriorityQueue<Integer> pq = new PriorityQueue<>((o1, o2) -> o2 - o1); // 전 이렇게 자주 사용했는데, 오버플로우 위험이 있다네요 -_- 하지만 한 번도... 읍읍
PriorityQueue<Integer> pq = new PriorityQueue<>((o1, o2) -> Integer.compare(o2,o1));
}
}
| 분류 | 함수 | 시간복잡도 | 파라미터 | 설명 |
|---|---|---|---|---|
| 추가 | offer(E e) | O(log N) | 추가할 원소 | 원소를 우선순위에 맞게 추가, 실패 시 false |
| 추가 | add(E e) | O(log N) | 추가할 원소 | 원소를 우선순위에 맞게 추가, 실패 시 예외 |
| 최우선 조회 | peek() | O(1) | - | 우선순위가 가장 높은 원소 반환, 비어 있으면 null |
| 최우선 조회 | element() | O(1) | - | 우선순위가 가장 높은 원소 반환, 비어 있으면 예외 |
| 최우선 삭제 | poll() | O(log N) | - | 우선순위가 가장 높은 원소 삭제 후 반환, 비어 있으면 null |
| 최우선 삭제 | remove() | O(log N) | - | 우선순위가 가장 높은 원소 삭제 후 반환, 비어 있으면 예외 |
| 특정 원소 삭제 | remove(Object o) | O(N) | 삭제할 원소 | 해당 원소를 찾아 삭제 |
| 포함 여부 | contains(Object o) | O(N) | 찾을 원소 | 해당 원소가 있는지 확인 |
| 전체 추가 | addAll(Collection<? extends E> c) | O(M log(N + M)) | 추가할 컬렉션 | 컬렉션의 원소를 모두 추가 |
| 전체 삭제 | clear() | O(N) | - | 모든 원소 삭제 |
| 비어 있는지 | isEmpty() | O(1) | - | 원소가 하나도 없는지 |
| 크기 | size() | O(1) | - | 원소 개수 |
| 배열 변환 | toArray() | O(N) | - | 배열로 변환 |
Java에는 그래프라는 자료구조는 없습니다. 모든 언어가 그렇듯 직접 구현해야 합니다.
대표적인 구현 방법은 인접 리스트, 인접 행렬, 간선 리스트입니다.
각 정점마다 연결된 정점들의 목록을 저장하는 방식입니다.
저는 주로 그래프는 인접리스트를 이용해서 구현합니다.
class Main {
public static void main(String[] args) throws Exception {
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i <= N; i++) {
graph.add(new ArrayList<>());
}
graph.get(1).add(2);
graph.get(1).add(3);
graph.get(2).add(4);
// 가중치가 있으면 int[] { 다음 정점, 가중치 } 로 저장
List<List<int[]>> graph = new ArrayList<>();
for (int i = 0; i <= N; i++) {
graph.add(new ArrayList<>());
}
graph.get(1).add(new int[] { 2, 5 });
graph.get(1).add(new int[] { 3, 2 });
// 순회
for (int[] edge : graph.get(now)) {
int next = edge[0];
int cost = edge[1];
}
}
}
O(V + E)O(degree(V))O(degree(V))O(1)
graph[i][j]에 정점 i와 j의 연결 여부 또는 가중치를 저장하는 방식입니다.
정점 수가 작거나 모든 정점의 연결 여부를 자주 확인해야 할 때 사용합니다.
class Main {
public static void main(String[] args) throws Exception {
int[][] graph = new int[N + 1][N + 1];
graph[1][2] = 1;
graph[1][3] = 1;
// 가중치 그래프는 가중치 저장
graph[1][2] = 5;
graph[2][1] = 3;
}
}
O(V²)O(V)O(1)O(1)그래프의 모든 간선을 하나의 리스트에 저장하는 방식입니다.
class Main {
public static void main(String[] args) throws Exception {
List<int[]> edges = new ArrayList<>();
// { 출발 정점, 도착 정점, 가중치 }
edges.add(new int[]{ 1, 2, 5 });
edges.add(new int[]{ 1, 3, 10 });
// 순회
for (int[] edge : edges) {
int from = edge[0];
int to = edge[1];
int cost = edge[2];
}
}
}
O(E)O(E)O(E)O(E)O(1)| 구분 | ArrayList<Integer> | LinkedList<Integer> | int[] |
|---|---|---|---|
| 구조 | 동적 배열 | 연결 리스트 | 고정 배열 |
| 크기 변경 | ✅ | ✅ | ❌ |
| 인덱스 조회 | O(1) | O(N) | O(1) |
| 마지막 추가 | 평균 O(1) | O(1) | ❌ |
| 중간 삽입·삭제 | O(N) | 탐색 포함 O(N) | 직접 이동 |
| primitive 저장 | ❌ | ❌ | ✅ |
| 코테 사용 빈도 | ⭐⭐⭐⭐⭐ | ⭐ | ⭐⭐⭐⭐⭐ |
ArrayListO(1))O(N))LinkedListO(N)ArrayDeque 사용 권장int[]여러 값을 이용해 List를 간단하게 생성할 수 있습니다.
class Main {
public static void main(String[] args) throws Exception {
List<Integer> list1 = List.of(1, 2, 3);
List<Integer> list2 = Arrays.asList(1, 2, 3);
}
}
둘 다 크기가 고정되어 있어 add(), remove()는 사용할 수 없습니다.
| 구분 | List.of() | Arrays.asList() |
|---|---|---|
add(), remove() | ❌ | ❌ |
set() | ❌ | ✅ |
null 저장 | ❌ | ✅ |
| 원본 배열과 연결 | ❌ | ✅ |
class Main {
public static void main(String[] args) throws Exception {
List<Integer> list = new ArrayList<>(List.of(1, 2, 3));
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
}
}
정렬의 기본은 오름차순입니다.
배열을 정렬할 때 사용합니다.
primitive 배열은 Comparator를 사용할 수 없고, 객체 배열(Integer[])은 Comparator를 사용할 수 있습니다.
class Main {
public static void main(String[] args) throws Exception {
// 오름차순
int[] arr = new int[10];
Arrays.sort(arr);
// 내림차순(Wrapper 클래스여야 Comparator 사용 가능)
Integer[] arr2 = { 1, 2, 3 };
Arrays.sort(arr2, Comparator.reverseOrder());
}
}
Collection을 정렬할 때 사용합니다.
class Main {
public static void main(String[] args) throws Exception {
List<Integer> list = new ArrayList<>();
Collections.sort(list);
}
}
객체 내부에서 기본 정렬 기준을 정의합니다.
class Node implements Comparable<Node> {
int cost;
@Override
public int compareTo(Node o) {
return this.cost - o.cost;
// 또는 return Integer.compare(this.cost, o.cost);
}
}
정렬할 때마다 기준을 바꾸고 싶을 때 사용합니다.
Collections.sort(list, (o1, o2) -> {
if (o1.cost != o2.cost) return o1.cost - o2.cost;
// 또는 return Integer.compare(o1.cost, o2.cost);
return o1.idx - o2.idx;
});
length vs length() vs size()length: 배열의 길이length(): String의 길이size(): Collection의 길이class Main {
public static void main(String[] args) throws Exception {
int[] arr = new int[10];
System.out.println(arr.length); // 10
String str = "안녕하세요";
System.out.println(str.length()); // 5
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
System.out.println(list.size()); // 3
// 이하 동일
set.size();
map.size();
}
}
class Main {
public static void main(String[] args) throws Exception {
Math.max(a, b); // 최대
Math.min(a, b); // 최소
Math.abs(x); // 절대값
Math.sqrt(x); // 루트
Math.pow(a, b); // 제곱수
Math.ceil(x); // 올림
Math.floor(x); // 내림
Math.round(x); // 반올림
}
}
class Main {
public static void main(String[] args) throws Exception {
int n = Integer.parseInt(str);
long l = Long.parseLong(str);
String s = String.valueOf(n);
}
}
이 두 개만 import하면 99%는 다 커버할 수 있습니다.
(사실 전 한 번도 이 이상 import 해본적이 없지만 혹시 몰라서 1% 남겨두겠습니다 ㅎㅎ)
import java.io.*;
import java.util.*;
중간중간 귀찮아서 AI한테 맡긴 것도 있지만, 내용 자체는 제 경험을 바탕으로 생각해낸거니 믿으셔도 됩니다.
필요한 내용은 추후 추가하겠습니다.
오랜만에 코테 풀 때마다 항상 까먹곤했는데 이렇게 정리해주셔서 감사합니다!