[백준] 2588번 : 곱셈 - JAVA [자바]
https://www.acmicpc.net/problem/2588
-
문제
매우 간단한 문제다!
- 3개의 풀이 방법을 제시한다.
이 문제는 하나로 입력된 문자(숫자)를 분리하여 연산을 할 수 있는지를 확인하는 문제다.
그래서 필자가 문제 접근 방법을 3가지로 나누어서 제시하고 마지막으로는 보너스로 성능을 개선한 코드까지 합하여 3+1 코드를 보여주려 한다.
- 알고리즘
첫 번째 입력으로 들어오는 세 자리수 정수에 두 번째 입력으로 들어오는 정수를 분리하여 각 각 곱한 값을 출력(3~5) 한 뒤 마지막에는 원래 식의 연산 값을 출력해주어야 한다.
그럼 두 번째 입력값을 어떻게 분리해주어야 하냐의 문제인데 방법은 크게 3가지가 있다.
- 문자열로 입력받아 charAt() 으로 하나씩 꺼내 쓰는 방법
- 나머지와 나눗셈 연산을 통해 각 자릿수를 구하여 쓰는 방법
- 문자열을 character 배열로 한 자리씩 넣어주어 이용하는 방법
여기서 1번과 3번의 방법은 문자열로 입력받기 때문에 가장 마지막 출력(6) 에서는 연산하기 위해서 int형으로 변환해주어야 한다.
가장 일반적으로 가장 쉽고 많이 쓰는 방법이 1번이라고 생각된다.
그럼 각각의 방법으로 풀어보자.
- 풀이
- 방법 1
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int A = in.nextInt();
String B = in.next();
in.close();
System.out.println(A * (B.charAt(2) - '0'));
System.out.println(A * (B.charAt(1) - '0'));
System.out.println(A * (B.charAt(0) - '0'));
System.out.println(A * Integer.parseInt(B));
}
}
가장 대중적인 방법이다.
먼저 Scanner을 이용하여 A는 int로, B는 String 으로 입력받는다.
그리고 B 는 charAt() 으로 각 자리수를 참조해준다. 참고로 JAVA API 문서에서 charAt() 에 대한 설명은 이러하다.
즉, 문자열의 인덱스 위치에 있는 문자(Character) 값을 반환한다.
그림으로 쉽게 이해해보자면
str 에 문자열 abcdef 가 저장되어있을 때 문자열을 문자들이 모인 배열이라고 보고 인덱스를 참조하여 해당 문자를 반환하는 것이다.
이때 반환되는 값은 아스키코드값인 문자 (char)이다.
String num = 345; 가 있다고 하자.
int result = num.charAt(0);라고 하면 result = 3 으로 착각할 수 있으나 실은 문자의 '3' 이지 숫자 3 이 아니라는 것이다.
즉, result = 51 이 저장되는 것이다.
아스키 코드값을 보려면 아래 사진을 참고하면 된다.
그렇기에 풀이 방법에도 각각의 문자열 인덱스를 참조한 뒤 -'0' 을 해주는 이유 또한 우리가 문자로 저장된 숫자가 아닌 우리가 보는 숫자 그대로의 값을 쓰기 위한 것이다.
마지막 출력은 전체 곱한 결과를 출력하면 되므로 우리가 입력받은 문자열을 숫자로 바꿔주는 Integer.parseInt()을 통해 문자열을 int형으로 바꿔주어 A와 곱해준 값을 출력하면 문제는 끝난다.
- 방법 2
숫자를 수학적으로 접근하여 푸는 방법이다.
이 문제의 포인트는 B에 들어오는 입력값을 각 자릿수 별로 얻어오는 것이다.
그럼 두번째 입력으로 들어오는 385 의 각 자릿수 값을 어떻게 구할까?
일의 자리 5의 경우 385 % 10 을 해주면 10으로 나눠준 값의 나머지를 구하니 5가 반환이 될 것이다.
십의자리 8은 385%100 을 해주면 85 가 나오고 이걸 10으로 나누면, 즉 85/10 을 하면 8이 반환 될 것이다.
백의자리 3은 385/100 을 하면 3이 나온다.
아래 코드를 보자.
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int A = in.nextInt();
int B = in.nextInt();
in.close();
System.out.println(A*(B%10));
System.out.println(A*(B%100/10));
System.out.println(A*(B/100));
System.out.println(A*B);
}
}
Scanner 로 입력을 받으면 시간이 오래걸리니 더 성능이 좋은 bufferedReader 을 이용하여 짤 수도 있다.
보고싶으면 아래 더 보기를 누르면 된다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main{
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int A = Integer.parseInt(br.readLine());
int B = Integer.parseInt(br.readLine());
br.close();
StringBuilder sb = new StringBuiler();
sb.append(A * (B%10));
sb.append('\n');
sb.append(A * ((B%100)/10));
sb.append('\n');
sb.append(A * (B/100));
sb.append('\n');
sb.append(A * B);
System.out.print(sb);
}
}
- 방법 3
이 방법은 조금 복잡한데 이러한 방법도 있구나~ 라고 생각하시면 될 것 같다.
문자열로 입력받음과 동시에 char 배열에 각 단어를 담아주어 쓰는 방법이다.
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 A = Integer.parseInt(br.readLine());
String B = br.readLine();
char[] b = B.toCharArray();
System.out.println(A * (b[2]-'0'));
System.out.println(A * (b[1]-'0'));
System.out.println(A * (b[0]-'0'));
System.out.println(A * Integer.parseInt(B));
}
}
toCharArray() 라는 문자열을 char 배열 형태로 반환해주는 메소드가 있다.
JAVA API 에서의 설명은 이러하다.
즉 위 메소드로 character 배열로 만들어준 뒤 하나씩 배열에서 꺼내서 쓰는 방법이다.
나중에 문자열 길이가 가변적으로 입력으며 문자 하나씩 참조해야할 때 매우 유용한 메소드 중 하나다.
- 보너스 [성능 개선 코드]
필자가 이번 문제를 풀 때 낸 코드다.
본인은 성능에 집착하는 면이 있어 최대한 성능이 좋은 방법을 끌어다 쓰려고 한다만...
꼭 이 방법이 어떠한 코드보다 완전 우월하다가 아닌 평균적으로 좋은 성능이다라는 정도만 알아두셨으면 한다.
그래도 나름 몇 개의 문제는 JAVA 맞은사람 중 상위랭크에 있는 것들도 있다.. (자기자랑)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main{
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int A = Integer.parseInt(br.readLine());
int B = Integer.parseInt(br.readLine());
br.close();
StringBuilder sb = new StringBuilder();
sb.append(A * (B%10));
sb.append('\n');
sb.append(A * ((B%100)/10));
sb.append('\n');
sb.append(A * (B/100));
sb.append('\n');
sb.append(A * B);
System.out.print(sb);
}
}
필자는 이 문제를 해결할 때 2번 방법을 사용했다.
아무래도 간단한 연산이 문자열을 참조하는 것보다 빠르기 때문에..
그리고 어지간하면 StringBuilder 나 BufferedWriter 로 문자열 출력방식을 택한다.
아마 이 문제에서는 별 성능차이가 없겠지만 문제가 뒤로 가면 갈수록 성능이 좋아지는 걸 느낄 수 있을 것이다..
아 그리고 Scanner 로 입력받는것과 BufferedReader 로 입력받는 것은 성능차이가 확연하게 난다.
그래서 필자는 입력받을때는 거의 무조건 BufferedReader 를 쓴다.
- 성능 차이
위에서 부터 순서대로
채점 번호 : 17599767 - 보너스 ( Scanner + 수학연산 )
채점 번호 : 17599755 - 방법 3 ( BufferedReader + toCharArray )
채점 번호 : 17599750 - 방법 2 ( Scanner + 수학연산 )
채점 번호 : 17599742 - 방법 1 ( Scanner + charAt() )
참고로 4ms 는 백준알고리즘에서 유의미한 차이까지는 아니다.
서버 상태 등 환경에 따라 같은 코드더라도 메모리, 시간이 달라 질 수 있다.
시간을 보면 BufferedReader 와 Scanner 의 성능차이가 확연하게 나는 것을 볼 수가 있다.
- 정리
문자열 입출력 part 는 이걸로 끝이다.
대체적으로 쉬운 문제인 만큼 입출력에 대해 여러 방법들을 익히고 기초를 단단히 할 수 있었으면 좋겠다.
'JAVA - 백준 [BAEK JOON] > 입출력과 사칙연산' 카테고리의 다른 글
[백준] 10926번 : ??! - JAVA [자바] (0) | 2022.06.17 |
---|---|
[백준] 25083번 : 새싹 - JAVA [자바] (2) | 2022.05.07 |
[백준] 10430 번 : 나머지 - JAVA [자바] (6) | 2020.02.09 |
[백준] 10869번 : 사칙연산 - JAVA [자바] (8) | 2020.02.08 |
[백준] 1008번 : A/B - JAVA [자바] (0) | 2020.02.08 |