안녕하세요
인포돈입니다.
백준 알고리즘 4344번 풀이입니다.
* 참고사항
- 개발환경은 eclipse을 기준으로 작성되었습니다.
- java언어를 이용하여 문제를 풀이합니다.
- 알고리즘 문제는 풀이를 보고 해답을 찾는 것도 중요하지만 무엇보다 스스로 풀이를 시도해봐야 합니다!!
(해당 풀이를 보기 전 충분히 문제에 대해 고민해봐야 합니다!)
- 해당 풀이 말고도 수많은 풀이 방법이 존재합니다.
백준 4344 (평균은 넘겠지)
문제
대학생 새내기들의 90%는 자신이 반에서 평균은 넘는다고 생각한다. 당신은 그들에게 슬픈 진실을 알려줘야 한다.
입력
첫째 줄에는 테스트 케이스의 개수 C가 주어진다.
둘째 줄부터 각 테스트 케이스마다 학생의 수 N(1 ≤ N ≤ 1000, N은 정수)이 첫 수로 주어지고, 이어서 N명의 점수가 주어진다. 점수는 0보다 크거나 같고, 100보다 작거나 같은 정수이다.
출력
각 케이스마다 한 줄씩 평균을 넘는 학생들의 비율을 반올림하여 소수점 셋째 자리까지 출력한다.
입력 예시
5
5 50 50 70 80 100
7 100 95 90 80 70 60 50
3 70 90 80
3 70 90 81
9 100 99 98 97 96 95 94 93 91
출력 예시
40.000%
57.143%
33.333%
66.667%
55.556%
성공코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int casenum = Integer.parseInt(br.readLine());
double[] db = new double[casenum];
for(int i = 0 ; i < casenum ; i++) {
double c = 0;
double sum = 0;
double count = 0;
StringTokenizer stt = new StringTokenizer(br.readLine());
c = Integer.parseInt(stt.nextToken());
double[] input = new double[(int)c];
//input change doubleArray & sum
for(int k=0; k < c;k++) {
if(stt.hasMoreTokens())
input[k] = Double.parseDouble(stt.nextToken());
sum += input[k];
}
//subject average
for(int l=0;l<c;l++)
if( input[l] > sum/c)
count ++;
db[i] = (count/c)*100;
}
for(double d : db) {
System.out.println(String.format("%.3f", d) + "%");
}
}//main
}
해당 코드에서 핵심사항은 크게 2가지로 생각이 된다.
어떻게 평균을 넘는 비율을 표현할 것인가?
어떻게 소수점 3자리에서 반올림을 하여 표현할 것인가?
이 두 가지 의문을 차례차례 풀이해 보겠습니다.
어떻게 평균을 넘는 비율을 표현할 것인가?
해당 의문을 해결하기 위해서 무엇이 필요할까요?
입력의 첫 번째 예시를 생각해보죠
5 50 50 70 80 100
5개의 점수가 있습니다. 우선 평균을 알아야 넘는 비율을 알 수 있겠죠?
평균을 구해보면 70점인 것을 알 수 있습니다. 평균이 70점이니 저 중에 70점을 넘기는 점수는 80점 100점이 있죠
그렇다면, 5개 중 2개가 평균을 넘는 거죠 2/5 = 0.4 여기에 백분율로 표현하기 위해 100을 곱하면 40% 저희가 원하는 결과 값이 나오죠.
슬슬 감이 오신 분도 있을 겁니다.
- 배열에 해당 점수들을 넣는다.
- 해당 점수들의 평균을 구한다.
- 조건문을 활용하여 평균을 넘는 점수들을 count 한다.
- 평균 이상 비율을 출력한다.
이런 식으로 큰 윤곽을 잡을 수 있죠
두 번째 의문인 어떻게 소수점 3자리에서 반올림하여 출력을 할까?
이문제는 검색을 통해 쉽게 찾을 수 있습니다.
소수점 반올림을 위해서는 대표적으로 String.format방식과 Math.round방식이 있습니다.
1. Math.round()
double pie = 3.14159265358979;
System.out.println(Math.round(pie)); //결과 : 3
System.out.println(Math.round(pie*100); //결과 : 314
System.out.println(Math.round((pie*100)/100.0); //결과 : 3.14
pie*100을 하면 314 값이 반환이 됩니다. 거기에 다시 100을 나누어주면 3.14 반올림이 된 걸 알 수 있죠
2. String.format()
double pie = 3.14159265358979;
System.out.println(String.format("%.2f", pie)); //결과 : 3.14
System.out.println(String.format("%.3f", pie)); //결과 : 3.142
쉽게 해결할 수 있습니다 %. 2f 즉, 소수점 2번째 자리에 반올림을 하라는 소리죠
2가지 방법 중 편하실걸을 이용하셔서 풀이하시면 됩니다.
그러나!!!! 저희는 언제나 더 나은 방법을 생각해볼 필요가 있습니다. 제가 작 상한 코드는 속도나 메모리를 잡아먹는 면에서 굉장히 비효율 적인 것을 알 수 있죠. 그래서 print대신 Bufferedwriter을 이용해서 다시 작성해보았습니다.
다른 성공 코드
import java.io.*;
import java.util.StringTokenizer;
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 casenum = Integer.parseInt(br.readLine());
double[] db = new double[casenum];
for(int i = 0 ; i < casenum ; i++) {
double c = 0;
double sum = 0;
double count = 0;
StringTokenizer stt = new StringTokenizer(br.readLine());
c = Integer.parseInt(stt.nextToken());
double[] input = new double[(int)c];
//input change doubleArray & sum
for(int k=0; k < c;k++) {
if(stt.hasMoreTokens())
input[k] = Double.parseDouble(stt.nextToken());
sum += input[k];
}
//subject average
for(int l=0;l<c;l++)
if( input[l] > sum/c)
count ++;
db[i] = (count/c)*100;
bw.write(String.format("%.3f", db[i]) + "%");
bw.write("\n");
}
bw.flush();
bw.close();
br.close();
}//main
}
이것보다 더 빠르게 하신 순위권들 분들도 있어서 어떻게 그렇게 했는지 복사하여 제 컴퓨터로 제출해봤는데, 순위권들과는 또 다른 속도와 메모리 사용량을 보여주더군요.
이를 보면, 똑같은 코드여도 속도나 메모리 사용량이 달라질 수 있음을 알 수 있고 정확한 이유는 아직 찾지 못했네요 ㅜㅜ 나중에 알게 되면, 알려드리겠습니다 ~
'알고리즘 > 백준알고리즘' 카테고리의 다른 글
[백준알고리즘-JAVA]11720번 풀이(숫자의 합) (0) | 2021.04.05 |
---|---|
[백준알고리즘-JAVA]4673번 풀이(셀프넘버) (1) | 2021.04.04 |
[백준알고리즘-JAVA]1546번 풀이(평균) (0) | 2021.04.02 |
[백준알고리즘-JAVA]10818번, 2562번 풀이(최대, 최소 / 최댓값) (0) | 2021.04.01 |
[백준알고리즘-JAVA]1110번 풀이(더하기사이클) (0) | 2021.03.31 |