[백준] 2577번 : 숫자의 개수 - JAVA [자바]
https://www.acmicpc.net/problem/2577
- 문제
문제 자체는 그리 어렵지 않은 것 같다. 문자열 분리 방법만 알고있다면 매우 쉬울거라 본다.
- 3가지 방법을 제시한다.
먼저 기초입력(Scanner)과 함께 가장 기본적인 알고리즘으로 풀어볼 것이다.
그리고 나머지 두 가지 방법은 BufferedReader 를 이용하여 알고리즘을 달리하여 풀어보고자 한다.
- 풀이
- 방법 1
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int value = (in.nextInt() * in.nextInt() * in.nextInt());
String str = Integer.toString(value);
in.close();
for (int i = 0; i < 10; i++) {
int count = 0;
for (int j = 0; j < str.length(); j++) {
if ((str.charAt(j) - '0') == i) {
count++;
}
}
System.out.println(count);
}
}
}
가장 보편적인 방법이 되지 않을까 싶다.
먼저 간단하게 설명을 하자면 다음과 같다.
in.nextInt() 로 입력과 동시에 곱해주어 value 에 담는다.
그리고 Integer.toString() 메소드를 사용하여 int 형을 String 으로 타입을 변환시킨후 str 에 담는다.
첫 번째 for문은 0~9 까지 각각의 수를 검사할 반복문이다.
그리고 count 로 개수를 카운트 하기 위한 변수를 0으로 초기화 한 후, 이중 for문을 통해 str의 길이만큼 모든 요소를 검사 charAt() 을 통해 해당 인덱스의 문자와 i 가 같은 수가 몇개 있는지 보며 만약 같을 경우 count를 +1 증가시킨다.
그리고 이중 for문이 끝나면 count 값을 출력시킨다.
그리고 반드시 charAt() 을 쓸 경우 - '0' 또는 -48 을 연산해야 한다. (아니면 아스키코드에 대응하는 문자가 나온다.)
다만 이 알고리즘은 시간복잡도가 O(N^2) 이라 좋은 코드는 아니다.
- 방법 2
BufferedReader 을 쓰는 방식이다.
그리고 BufferedReader 는 문자열로 반환되니 String을 Int 형으로 변환해주어야 한다.
String 에서 Int 로 변환하는 메소드는 Integer.parseInt() 다.
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[] arr = new int[10];
int val = Integer.parseInt(br.readLine()) * Integer.parseInt(br.readLine()) * Integer.parseInt(br.readLine());
String str = String.valueOf(val);
for (int i = 0; i < str.length(); i++) {
arr[(str.charAt(i) - 48)]++;
}
for (int v : arr) {
System.out.println(v);
}
}
}
이 방법은 첫 번째 방법에 비해 알고리즘상 시간복잡도가 O(N) 이라 훨씬 수행속도가 짧다.
또한 BufferedReader 자체가 Scanner 에 비해 우월한 성능을 지니고 있어 훨씬 좋은 performance 를 보여준다.
알고리즘 방식은 다음과 같다.
먼저 0부터 9까지 체크할 길이 10의 int 배열을 생성한다. (기본 int배열 초기값은 모두 0이다.)
그리고 val 에다가 br.readLine() 으로 읽은 값을 곱해서 저장한다.
그리고 String str 에다가 val 의 Int 형을 String 형으로 변환해준 뒤 for문을 통해 해당 문자열의 문자 값 - 48 (또는 -'0')을 추출해내 int 배열의 index 값을 1 증가시킨다.
마지막으로 배열 원소에 저장된 모든 원소를 출력한다.
- 방법 3
다른 방법으로는 몫, 나머지 연산을 통한 방법이다.
아래 코드를 보자.
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 val = Integer.parseInt(br.readLine())*Integer.parseInt(br.readLine())*Integer.parseInt(br.readLine());
int[] arr = new int[10];
while(val!=0) {
arr[val%10]++;
val/=10;
}
for(int result : arr) {
System.out.println(result);
}
}
}
기본적인 변수 할당은 앞선 코드들과 방법이 같다.
달라진 점이라면 String으로 변환해줄 필요 없이 나머지 연산과 몫 연산으로 한다는 것이다.
먼저 while 문의 조건으로 val 이 0 이 아니면 반복을 돌도록 한다.
그리고 val % 10 의 값. 즉, 나머지 값을 배열의 index 로 활용하여 해당 인덱스의 값을 1 증가시켜주는 것이다.
그런 뒤 val = val/10; 을 통해 한 자릿수씩 줄여나간다.
위와 같은 방법도 매우 좋은 방법이긴 하다.
굳이 String 으로 변환 할 필요도 없고. String.charAt() 메소드를 쓰지 않아도 되니깐.
- 성능 차이
위에서 부터 순서대로
채점 번호 : 18022104 - BufferedReader + (% /) Operator
채점 번호 : 18022096 - BufferedReader + String.charAt()
채점 번호 : 18022086 - Scanner
시간을 보면 BufferedReader 와 Scanner 의 성능차이가 확연하게 나는 것을 볼 수가 있다.
- 정리
그리 어려운 문제는 아니었다.
사실 보면 String 문자열 자체가 char (문자)의 배열 형태로도 볼 수 있다. 그래서 charAt() 또한 String 을 하나의 배열로 보고 index 처럼 활용하는 것이다.
여러 알고리즘 방법이 있으니 독자분들이 잘 보고 뭐가 본인에게 맞는지에 따라 선택하여 풀어나가면 되겠다.
'JAVA - 백준 [BAEK JOON] > 기타 문제' 카테고리의 다른 글
[백준] 10039번 : 평균 점수 - JAVA [자바] (0) | 2020.03.13 |
---|---|
[백준] 5543번 : 상근날드 - JAVA [자바] (0) | 2020.03.04 |
[백준] 2742번 : 기찍 N - JAVA [자바] (6) | 2020.02.18 |
[백준] 2741번 : N 찍기 - JAVA [자바] (11) | 2020.02.18 |
[백준] 10817번 : 세 수 - JAVA [자바] (2) | 2020.02.14 |