오늘은 반복문, 1차원 배열을 단계별 문제로 풀었다.
반복문 12문제, 1차원 배열문제 10문제 총 22문제를 풀었다.
확실히 이전에 풀었던 입출력과 조건문 보다는 출력조건이나 푸는 방식이 까다로워졌음을 느꼈다.
이번에 풀었던 문제중에서 인상깊었던 문제 몇 개를 적어본다.
백준 15552 - 빠른 A+B
https://www.acmicpc.net/problem/15552
문제 분석
문제가 길지만, 요약해서 그냥 A,B를 받아서 A+B를 출력하면 된다.
여기서 주의해야할 점은, 테스트 케이스의 T를 입력받아서 그 횟수만큼 출력을 해야하는데, T가 1,000,000까지의 값을 가질 수도 있다.
시간제한이 1초이므로, 한번에 많은양의 처리를 수행해야한다.
이럴 때는 Scanner(System.in)으로 받아서 입력을 처리하기 보다는 BufferedReader, BufferedWriter를 사용한다.
BufferedReader와 BufferedWriter는 입출력 스트림을 버퍼링하여 데이터를 더 효율적으로 처리하는데 도움을 준다. BufferedReader와 BufferedWriter는 내부적으로 데이터를 버퍼에 미리 읽거나 쓰기 때문에 입출력 횟수가 줄어들고, 시스템 호출이 감소하여 입출력 속도가 향상된다.
Scanner는 버퍼링을 하지 않고 직접적으로 입력 스트림을 읽기 때문에 여러 번의 시스템 호출이 발생할 수 있다.
정답
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
// 입출력을 빠르게 하기 위해서 BufferedReader, BufferedWriter 사용하기
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int T = Integer.parseInt(br.readLine());
for (int i = 0; i < T; i++) {
String[] input = br.readLine().split(" ");
int num1 = Integer.parseInt(input[0]);
int num2 = Integer.parseInt(input[1]);
bw.write(Integer.toString(num1 + num2));
bw.newLine();
}
// 버퍼 비우고 닫기
bw.flush();
bw.close();
br.close();
}
}
입출력을 각각 br, bw로 만들어준다.
T는 br.readLine으로 테스트 케이스의 숫자를 받아준다.(한줄을 읽어들)
T만큼 반복하면서, 숫자를 2개 받아서 bw.write로 출력해준다.
이후 bw.newLine으로 새로운 줄로 이동해줘야한다.
루프가 끝나면 flush로 버퍼를 비우고, close로 닫아줘야 한다.
백준 10952 - A + B - 5 (끝나지 않는 루프)
https://www.acmicpc.net/problem/10952
문제 분석
문제는 특별할 것 없이 A+B를 출력하는 문제이다.
여기서 주의할 점은 테스트케이스 횟수를 받지 않고 계속해서 받아야 한다는 것이다.
마지막에는 '0' 두 개를 받는다는 조건이 있다.
그러면 이 '0' 두 개를 테스트케이스의 종료를 알리는 조건으로 만들면 된다.
정답
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
while (true) {
String[] input = br.readLine().split(" ");
int num1 = Integer.parseInt(input[0]);
int num2 = Integer.parseInt(input[1]);
int sum = num1 + num2;
if (sum == 0 && num1 == 0 && num2 == 0) {
break; // 입력이 모두 0인 경우 while 루프 종료
}
if (sum != 0) {
bw.write(Integer.toString(sum));
bw.newLine();
}
}
// 버퍼 비우고 닫기
bw.flush();
bw.close();
br.close();
}
}
이전에 풀었던 A+B와 같이 buffer로 입출력 처리를 하고, if문으로 조건을 추가했다.
입력 숫자와 합 모두 0이 되는 순간 while(true)의 루프를 종료시킨다.
만약 0이 아니라면 계속해서 write로 A+B의 결과를 출력한다.
백준 10813 - 공 바꾸기
https://www.acmicpc.net/problem/10813
문제 분석
공 바꾸기 문제이다.
문제는 백준 10810 공 넣기 문제와 비슷하지만, 요약하자면, 아래와 같다.
1. 바구니가 N개 존재한다.
2. 바구니안에는 공이 1개씩만 넣을 수 있다. 처음에는 바구니 번호와 같은 공이 있다.
3. i, j, k 라는 값을 입력받아서 i 바구니와 j 바구니의 공을 교환한다.
4. 이 과정을 M번 반복한다.
5. 마지막으로 각 바구니에 공 번호를 출력하라.
공을 바꿔야 한다. 이 때, i 바구니의 공을 j 바구니의 공으로 바꾸고, j 바구니의 공을 i 바구니의 공으로 바꿔야 하는데, 이미 앞에서 i 바구니에는 j 바구니의 공이 들어가있으므로, j에는 j의 공이 다시 들어갈 것이다.
그러므로 변수를 하나 생성해서 i바구니의 공을 임시로 넣어두었다가 j 바구니에 전해줘야 한다.
정답
import java.util.Scanner;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int M = scanner.nextInt();
int[] basketN = new int[N];
for (int i = 0; i < N; i++) {
basketN[i] = i + 1; // 초기화
}
for (int i = 0; i < M; i++) {
int numI = scanner.nextInt();
int numJ = scanner.nextInt();
// 두 위치의 숫자를 교환
int temp = basketN[numI - 1];
basketN[numI - 1] = basketN[numJ - 1];
basketN[numJ - 1] = temp;
}
// 배열 출력
for (int value : basketN) {
System.out.print(value + " ");
}
scanner.close();
}
}
공을 배열에 넣어서 초기값을 준다.
이후 temp에 i 바구니의 공을 담아뒀다가, i 바구니에 j 공을 주고, j 바구니에 i 공을 전해준다.
백준 10811 - 바구니 뒤집기
https://www.acmicpc.net/problem/10811
문제 분석
바구니 바꾸기 문제이다.
문제는 백준 10813 공 바꾸기 문제와 비슷하지만, 범위의 순서를 통째로 역순으로 만들어야한다.
1. 바구니가 N개 존재한다.
2. 바구니 번호오는 순서대로 부여받는다.(1번째 바구니는 1.... N번째 바구니는 N)
3. i, j, k 라는 값을 입력받아서 i 과 j 범위의 바구니를 역순으로 교환한다.
4. 이 과정을 M번 반복한다.
5. 마지막으로 각 바구니를 출력하라.
구간의 교환을 진행해야 하므로 투 포인터를 사용한다.
start-end라는 두개의 포인터를 사용해서 시작과 끝의 번호를 계속 교환하면 역순이 되게 된다.
정답
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt(); // 배열의 크기
int M = scanner.nextInt(); // 명령의 개수
int[] basketN = new int[N];
// 배열 초기화
for (int i = 0; i < N; i++) {
basketN[i] = i + 1;
}
// 명령 실행
for (int i = 0; i < M; i++) {
int numI = scanner.nextInt();
int numJ = scanner.nextInt();
reverseArraySubset(basketN, numI - 1, numJ - 1); // 구간 역순으로 배치
}
// 배열 출력
for (int value : basketN) {
System.out.print(value + " ");
}
scanner.close();
}
// 배열의 일부 구간을 역순으로 배치하는 함수
private static void reverseArraySubset(int[] arr, int start, int end) {
while (start < end) {
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
}
}
reverseArraySubset이라는 함수를 만든다.
여기서는 i와 j를 받아서 start, end라는 포인터로 만들어서 입력한다.
인덱스는 0부터 시작하므로 -1을 뺀 상태로 함수에 집어넣어야 한다.
이 함수에서는 end가 start가 클 때까지만 두 값을 교환하는 동작을 계속 진행한다.
포인터는 end는 하나씩줄고, start는 하나씩 늘어난다.
'Code Test > Java' 카테고리의 다른 글
백준 단계별 풀이 - 심화1 (1) | 2023.12.27 |
---|---|
백준 단계별 풀이 - 문자열 (1) | 2023.12.23 |
백준 단계별 풀이 - 입출력과 사칙연산, 조건문 (0) | 2023.12.19 |
백준 2018 - 수들의 합 5 (1) | 2023.12.19 |
백준 11659 - 구간합 구하기 4 (0) | 2023.12.14 |