묠니르묘묘
꾸준히 성장하는 개발자스토리
묠니르묘묘
전체 방문자
오늘
어제
  • 분류 전체보기 (188)
    • 프로그래밍 (48)
      • 디자인패턴 (4)
      • 예외,에러 (4)
      • Java (29)
      • Kotlin (3)
      • React.js (4)
      • JavaScript (2)
      • Apache Kafka (2)
    • Spring (49)
      • Spring (21)
      • Spring Cloud (3)
      • JPA (25)
    • 코딩테스트 (31)
      • 알고리즘 (5)
      • Java - 백준 (26)
      • Java - 프로그래머스 (0)
    • AWS (7)
    • 데이터베이스 (6)
    • 개발 etc (23)
    • 도서 (5)
    • 회고록 (4)
    • 데브코스-데이터엔지니어링 (15)

인기 글

최근 글

hELLO · Designed By 정상우.
묠니르묘묘

꾸준히 성장하는 개발자스토리

[백준] 4344번 - Java(자바)
코딩테스트/Java - 백준

[백준] 4344번 - Java(자바)

2022. 1. 30. 17:32

백준 4344번 자바

https://www.acmicpc.net/problem/4344

 

4344번: 평균은 넘겠지

대학생 새내기들의 90%는 자신이 반에서 평균은 넘는다고 생각한다. 당신은 그들에게 슬픈 진실을 알려줘야 한다.

www.acmicpc.net

내용을 바로 보고싶으면 아래 더보기를 눌리면 된다.

더보기

 

 

 

알고리즘

첫째 줄에 테스트 케이스 개수 C가 주어진다.

둘째 줄부터 학생의 수 N이 주어지고, N명의 점수가 이어서 주어진다.

1 ≤ N ≤ 1000, N은 정수이고, 0 ≤ 점수 ≤ 100 이다.

 

 

1. 학생점수를 넣을 배열 arr, 점수의 합 sum, 평균을 넘은 학생 수 count를 만든다.

2. 테스트 케이스의 개수 C 입력받는다.

3. C만큼 반복한다.

   3-1. sum과 count를 0으로 초기화한다.

   3-2. 테스트 케이스 한 줄 입력받아 StringTokenizer로 글을 공백기준으로 나눈다.

   3-3. 학생의 수 N을 입력받는다.

   3-4. N만큼 arr 배열의 길이를 초기화한다.

   3-5. N만큼 반복한다.

      1) arr에 학생의 점수를 넣는다.

      2) sum에 학생의 점수를 더한다.

   3-6. 다시 N만큼 반복한다.

      1) 만약 평균( sum / N )보다 학생의 점수가 높으면 count를 1+한다.

   3-7. 소수점 셋째 자리까지 평균을 넘은 학생 비율( count / N )을 출력한다.

 

 

 

풀이1

import java.io.*;
import java.util.StringTokenizer;

public class No_4344 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        int[] arr;
        int sum, count;
        int C = Integer.parseInt(br.readLine());
        for (int i = 0; i < C; i++) {
            sum = 0;
            count = 0;
            st = new StringTokenizer(br.readLine());
            int N = Integer.parseInt(st.nextToken());
            arr = new int[N];
            for (int j = 0; j < N; j++) {
                arr[j] = Integer.parseInt(st.nextToken());
                sum += arr[j];
            }
            for (int j = 0; j < N; j++) {
                if ((float) sum / N < arr[j]) count++;
            }
            System.out.printf("%.3f%%\n", ((float) count / N) * 100);
        }
    }
}

알고리즘대로 풀었다.

학생들의 점수 평균을 구해서 평균을 넘는 학생을 구해야하기에 학생들의 값이 필요했다.

그래서 arr[] 에다가 값을 넣어 저장해둔 것인데 다른 방법은 생각나지 않는다.

소수점을 구해야하기에 실수인 float 또는 double을 써야하는데 그러면 int에 비해 메모리를 더 잡아먹으니까 int로 생성하고 실수가 필요한 계산에는 float로 강제형변환하여 풀었다.

 

반올림하여 나타내는 방식은 크게 3가지로 다음과 같다.

  • printf
  • String.format
  • Math.round

여기서는 printf에서 사용한 문자들의 뜻은 다음과 같다.

%.3f 는 소수점 3째자리까지 실수를 출력하겠다는 뜻이다.

%% 는 특수문자 %를 나타내기위해 두번 쓰였다.

\n 는 한 줄 띄어쓰기이다.

 

 

풀이2

Math.round 메서드로 반올림하여 풀려고 했는데 소수점 아래 0은 전부 삭제한다는 문제가 있었다.

그래서 이 방법은 쓸 수 없을거 같았는데 생각해보면 정수로 반올림을 해버리기때문에 소수점을 가지고있으려면 그만큼 곱한다음 정수로 만들고 그 후 다시 나눠야하는데 너무 복잡한것 같다.

 

후에 어떻게든 써보려고 했는데 예제는 다 맞췄는데 채점시 틀렸다고 나와서 어디가 문제인지 찾는중이다.

코드는 아래와 같다.

이렇게 하루를 풀어보았는데 못풀어서 내가 자주보는 블로거님에게 문의드렸더니

1

4 1 0 0 0

을 입력하면 25.0%가 나온다고 말해주셔서 바로 고쳐서 풀었다...!

코드는 아래와 같다.

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));
        StringTokenizer st;

        int[] arr;
        int sum, count;
        // 테스트케이스 개수 C 
        int C = Integer.parseInt(br.readLine());
        for (int i = 0; i < C; i++) {
            // 각 점수를 더할 sum과 평균을 넘는 학생의 수 count를 0으로 초기화한다.
            sum = 0;
            count = 0;
            st = new StringTokenizer(br.readLine());
            // 학생의 수 N
            int N = Integer.parseInt(st.nextToken());
            // 학생의 수만큼 배열을 만든다.
            arr = new int[N];
            // 학생의 점수를 배열에 넣은 후 sum에 더한다.
            for (int j = 0; j < N; j++) {
                arr[j] = Integer.parseInt(st.nextToken());
                sum += arr[j];
            }

            // 평균값 average
            float average = (float) sum / N;

            // 평균보다 높은 점수를 가진 학생의 수를 센다.
            for (int j = 0; j < N; j++) {
                if (average < arr[j]) count++;
            }

            // 평균을 넘는 학생들의 비율을 반올림한 number
            double number = Math.round((float) count / N * 100000);
            

            // number의 나머지가 0.0인지 아닌지 확인한다.
            if (number % 10 == 0.0) {
                // 0.0이면 소수점 3째자리까지 표현해야하므로 String.format으로 다시 비율을 구한다.
                System.out.println(String.format("%.3f%%", (float) count / N * 100));
            } else {
                // 나머지가 0.0이 아니라면 number에다가 %를 붙여서 끝낸다.
                System.out.println((number/1000) + "%");
            }
        }
    }
}

 

풀이3

import java.io.*;
import java.util.StringTokenizer;

public class No_4344 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        int[] arr;
        int sum, count;
        int C = Integer.parseInt(br.readLine());
        for (int i = 0; i < C; i++) {
            sum = 0;
            count = 0;
            st = new StringTokenizer(br.readLine());
            int N = Integer.parseInt(st.nextToken());
            arr = new int[N];
            for (int j = 0; j < N; j++) {
                arr[j] = Integer.parseInt(st.nextToken());
                sum += arr[j];
            }
            for (int j = 0; j < N; j++) {
                if ((float) sum / N < arr[j]) count++;
            }
            System.out.println(String.format("%.3f%%", (float) count / N * 100));
        }
    }
}

이번에는 String.format으로 문자형식을 지정해 출력하였다.

printf랑 비슷한 느낌이지만 이거는 나중에 원하는 소수점으로 계산을 해야할 때 String.format으로 값을 지정하면 좋을것 같다. 이 문제에서는 쓸 일이 없기에 printf로 하면 편할듯하다.

 

 

 

 

풀이4

import java.io.*;
import java.util.StringTokenizer;

public class No_4344 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st;

        int[] arr;
        int sum, count;
        int C = Integer.parseInt(br.readLine());
        for (int i = 0; i < C; i++) {
            sum = 0;
            count = 0;
            st = new StringTokenizer(br.readLine());
            int N = Integer.parseInt(st.nextToken());
            arr = new int[N];
            for (int j = 0; j < N; j++) {
                arr[j] = Integer.parseInt(st.nextToken());
                sum += arr[j];
            }
            for (int j = 0; j < N; j++) {
                if ((float) sum / N < arr[j]) count++;
            }
            bw.write(String.format("%.3f%%\n", (float) count / N * 100));
        }
        bw.flush();
    }
}

출력을 BufferedWriter로 바꿔보았는데도 성능은 비슷하다.

성능을 더 뽑아내려면 메서드를 만들어야하는 걸까?

테스트케이스가 많고, 메서드가 엄청 반복된다면 빠르게 JIT 컴파일하여서 좀 더 성능을 내지 않을까? 라고 생각해본다.

그렇다면 메서드는 함수(테스트케이스) 이렇게 보내버려서 그 메서드 안에서 처리를 하게 만들어봐야겠다.

메서드를 만들어보았는데 성능은 똑같았다.

 

 

 

참고

https://st-lab.tistory.com/51

저작자표시 (새창열림)

'코딩테스트 > Java - 백준' 카테고리의 다른 글

[백준] 4673번 - Java(자바)  (0) 2022.02.04
[백준] 15596번 - Java(자바)  (0) 2022.02.03
[백준] 8958번 - Java(자바)  (0) 2022.01.28
[백준] 1546번 - Java(자바)  (0) 2022.01.27
[백준] 3052번 - Java(자바)  (0) 2022.01.25
    '코딩테스트/Java - 백준' 카테고리의 다른 글
    • [백준] 4673번 - Java(자바)
    • [백준] 15596번 - Java(자바)
    • [백준] 8958번 - Java(자바)
    • [백준] 1546번 - Java(자바)
    묠니르묘묘
    묠니르묘묘

    티스토리툴바