[백준] 11022번 : A+B - 8 - JAVA [자바]
https://www.acmicpc.net/problem/11022
-
문제
매우 간단한 문제다!
※ 주의할 점
- 첫 줄에 테스트 케이스 개수가 입력되고 다음 입력부터는 공백을 기준으로 두 개의 정수가 입력된다.
- "Case #n: " 문자열 뒤에 A + B 와 그 연산 결과값이 출력된다.
- 2가지 풀이방법을 제시한다.
Scanner 로 입력받아 연산하는 방법과 BufferedReader 로 입력받아 연산하는 방법, 두 가지 방법을 통해 풀이해보고자 한다.
또한 출력방법도 변경해보면서 성능을 최대화하여 시간을 단축해보고자 한다.
추가로 필자가 제출한 코드도 보여주고자 한다.
기본 포멧은 바로 직전 포스팅인 A+B - 7 번과 같으므로 만약 참고하고자 한다면 아래 더보기에 있는 링크를 클릭하면 된다.
- 풀이
- 방법 1
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner in = new Scanner(System.in);
int T = in.nextInt();
for (int i = 1; i <= T; i++) {
int A = in.nextInt();
int B = in.nextInt();
System.out.println("Case #" + i + ": " + A + " + " + B + " = " + (A+B));
}
in.close();
}
}
가장 기초적인 풀이 방법이다.
- 방법 2
BufferedReader 을 쓰는 방식이다.
readLine() 을 통해 입력 받아 연산하는 방법 두 가지를 설명할 것이다.
앞서 말했듯이 readLine() 은 한 행을 전부 읽기 때문에 공백단위로 입력해 준 문자열을 공백단위로 분리해주어야 문제를 풀 수 있을 것이다.
고로 문자열 분리는 StringTokenizer 을 사용할 것이다.
그리고 반드시 자료형 타입을 잘 보아야 한다.
st.nextToken() 은 문자열을 반환하니 Integer.parseInt()로 int 형으로 변환시켜준다.
또한 출력방법을 달리하여 풀이하는 방법 또한 알려줄 것이다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.io.IOException;
public class Main {
public static void main(String args[]) throws IOException {
BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
int A;
int B;
StringTokenizer st;
for (int i = 1; i <= T; i++) {
st = new StringTokenizer(br.readLine()," ");
A = Integer.parseInt(st.nextToken());
B = Integer.parseInt(st.nextToken());
System.out.println("Case #" + i + ": " + A + " + " + B + " = " + (A+B));
}
br.close();
}
}
또 다른 출력 방법으로는 위 코드에서 StringBuilder 로 변경하여 쓰는 방법이다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.io.IOException;
public class Main {
public static void main(String args[]) throws IOException {
BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
int A;
int B;
StringBuilder sb = new StringBuilder();
StringTokenizer st;
for (int i = 1; i <= T; i++) {
st = new StringTokenizer(br.readLine()," ");
A = Integer.parseInt(st.nextToken());
B = Integer.parseInt(st.nextToken());
sb.append("Case #" + i + ": ").append(A + " + " + B + " = " + (A+B)).append('\n');
}
br.close();
System.out.println(sb);
}
}
물론 조금 더 복잡해졌긴 했다. 참고로 append 를 저렇게 나눠서 쓰는게 아닌 한 번에 써주어도된다.
sb.append("Case #"+ i + ": " + A + " + " + B + " = " + (A+B) + "\n" );
이런식으로 써주어도 된다. 근데 필자가 저렇게 나눠서 쓰는 이유는
직접 테스트해보면 알겠지만 저렇게 출력할 문자에 여러 타입이 너무 많이 섞여있으면 해당 메소드는 일일이 타입검사를 해주어야 하기 때문에 시간이 미약하게나마 더 걸리게 된다는 것이다. 물론 성능에 신경 안쓴다면 하나로 합쳐서 써도 무방하다.
물론 반대로 하나하나 다 나눠서 넣어줘도 무방하다!
또 다른 방법으로는 BufferedWriter 을 쓰는 방법이다.
아래 방법 또한 코드 자체는 복잡할지 몰라도 한 번 이해하면 써먹기 참 좋은 방법이다.
참고로 BufferedWriter.write() 메소드는 단독으로 int 형 값만 넣을경우 이는 아스키 코드값으로 인식되기 때문에 다른 문자가 나와버린다. 그러니 이를 방지하고 싶다면 반드시 문자열과 int 형을 함께 넣어줘야 int 값을 제대로 출력할 수 있다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedWriter;
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));
int T = Integer.parseInt(br.readLine());
int A;
int B;
StringTokenizer st;
for (int i = 1; i <= T; i++) {
st = new StringTokenizer(br.readLine()," ");
A = Integer.parseInt(st.nextToken());
B = Integer.parseInt(st.nextToken());
bw.write("Case #"+i+": ");
bw.write(A + " + " + B + " = ");
bw.write((A+B) + "\n");
}
br.close();
bw.flush();
bw.close();
}
}
- 더 좋은 방법 없을까?
이전 포스팅에서도 언급했지만 보다시피
시간을 최소화 하고싶다면 주어진 문제에서 최적의 알고리즘을 찾는 것이 중요하다.
문제를 잘 보자.
입력에서 A 와 B 의 범위는 0 초과 10 미만이다. 즉 1~9 사이라는 것이다.
그러면 문자열 분리할 때 공백이 들어가는 위치는 배열로 따질 때 다음과 같을 것이다.
A 와 B 는 "무조건" 한 자릿수만 입력받기 때문에 문자열로 입력받을시 공백이 들어가는 위치는 언제나 고정되어있다.
그럼 문자열의 특정 위치의 문자를 반환해주는 charAt() 을 쓸 수 있다면 StringTokenizer 객체를 계속 생성하지 않아도 되기에 시간이 더욱 단축 될 수 있을 것이다!
필자가 힌트를 주는 코드는 다음과 같다.
아래 코드를 보고 조금 더 고민해서 시간 단축을 할 수 있는 방법을 찾아 수정하면 충분히 상위권에 올라갈 수 있다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
public static void main(String args[]) throws IOException {
BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= T; i++) {
String str = br.readLine();
int A = str.charAt(0)-'0';
int B = str.charAt(2)-'0';
sb.append("Case #").append(i).append(": ").append(A)
.append(" + ").append(B).append(" = ").append(A+B).append('\n');
}
System.out.println(sb);
}
}
아 그리고 여러분들이 실수 할 수 있는 부분이 String.charAt() 은 해당 위치의 문자를 char 로 반환한다.
즉 만약 0이라는 문자열이 반환되면 아스키 코드값인 48이 반환된다.
이를 int형으로 연산하려고 하거나 문자 출력이 아닌 정수로 출력하려 하면 0 이라는 숫자가 아닌 48로 출력된다.
그러니 예로들어 문자 '6' 을 숫자 6 으로 바꾸고 싶다면 48을 빼주면 된다.
만약 몇을 빼줘야할지 모른다면 -'0' 으로 해도 된다.
- 성능 차이
위에서 부터 순서대로
채점 번호 : 17797679 - 필자 힌트 코드
채점 번호 : 17797666 - BufferedReader + BufferedWriter
채점 번호 : 17797654 - BufferedReader + StringBuilder
채점 번호 : 17797647 - BufferedReader + System.out.println()
채점 번호 : 17797632 - Scanner
위와같이 입력 메소드의 성능차이와 알고리즘 구현 방법에 따라 시간이 달라질 수 있음을 보여주고 있다.
- 정리
바로 직전 포스팅과 문제가 매우 유사하기 때문에 별다른 어려움이 없었을 것이다.
그래도 이렇게 하나하나 쉽더라도 누군가에게는 도움이 되리라 보고 열심히 포스팅 하겠다.
'JAVA - 백준 [BAEK JOON] > 반복문' 카테고리의 다른 글
[백준] 2439번 : 별 찍기 - 2 - JAVA [자바] (6) | 2020.02.19 |
---|---|
[백준] 2438번 : 별찍기 - 1 - JAVA [자바] (8) | 2020.02.19 |
[백준] 11021번 : A+B - 7 - JAVA [자바] (13) | 2020.02.19 |
[백준] 15552번 : 빠른 A+B - JAVA [자바] (34) | 2020.02.17 |
[백준] 8393번 : 합 - JAVA [자바] (5) | 2020.02.15 |