Algorithm/BOJ

[백준] solved.ac (in Java)

멍두 2024. 10. 18. 14:16
반응형

📍 문제

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

 

상,하위 15퍼센트 의견은 제외하고 평균을 낸 뒤 반올림하는 문제

쉬운 문제이지만 두 가지 방법으로 풀 수 있어서 글을 작성한다.

 

의견의 개수 n이 매우 크므로 이 부분에 유의 (0 ≤ n ≤ 3^105)

📍 코드 설명

첫번째 방법

가장 떠올리기 쉬운 방법

1. 의견을 배열에 받은 뒤 오름차순 정렬한다.

2. 상 하 15%를 계산한다.

3. 15%에 해당하는 index를 제외한 배열을 전부 더한 뒤 평균을 구한다

 

이 방법은 배열을 정렬할 때 평균 : O(nlog(n)) / 최악 : O(n^2),

전부 더할 때 입력의 수만큼 돌아야한다.

 

두번째 방법

countingSort를 이용한 방법

1. 배열 index를 점수라 생각하고, 점수가 들어올때마다 arr[index] += 1을 해준다

2. 상 하 15%를 계산한다

3. 하위 15% 의견을 제거한다

4. 상위 15% 점수를 제거한다

5. 배열을 전부 다 더한 뒤 평균을 구한다

 

이 방법은 정렬이 없고, 배열을 전부 다 더할 때도 30번만 돌기때문에 시간이 훨씬 빠르다

📍 코드

✔️ 첫번째 방법 코드

더보기
import java.io.*;
import java.util.*;

public class Main {

	public static void main(String...args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine());	//의견의 개수
		
		//제거할 인원 계산
		int removeCnt = (int)(n * 0.15 + 0.5);
		
		//의견 입력
		int[] arr = new int[n];
		for(int i = 0; i < n; i++) {
			arr[i] = Integer.parseInt(br.readLine());
		}
		
		//의견 정렬
		Arrays.sort(arr);
		
		//의견 계산
		double difficultySum = 0;
		for(int i = removeCnt; i < n - removeCnt; i++) {
			difficultySum += arr[i];
		}
		int answer = (int)(difficultySum / (n - removeCnt*2) + 0.5);
		
		System.out.println(answer);	
	}
}

✔️ 두번째 방법 코드

더보기
import java.io.*;
import java.util.*;

public class Main {

	public static void main(String...args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int n = Integer.parseInt(br.readLine());	//의견의 개수
		
		//제거할 인원 계산
		int removeCnt = (int)(n * 0.15 + 0.5);
		
		//의견 입력
		int[] arr = new int[31];
		for(int i = 0; i < n; i++) {
			int index = Integer.parseInt(br.readLine());
			arr[index] += 1;
		}
		
		//제외되는 사람 앞 부분 제거
		int idx = 1;
		int removed = 0;
		while(removed < removeCnt) {
			if (arr[idx] == 0) {
				idx++;
				continue;
			} 
			arr[idx]--;
			removed++;
		}
		
		//제외되는 사람  부분 제거
		idx = 30;
		removed = 0;
		while(removed < removeCnt) {
			if (arr[idx] == 0) {
				idx--;
				continue;
			} 
			arr[idx]--;
			removed++;
		}
		
		//의견 합 계산
		double difficultySum = 0;
		for(int i = 1; i < 31; i++) {
			difficultySum += (arr[i] * i);
		}
		
		//의견 결과 계산
		int answer = (int)(difficultySum / (n - removeCnt*2) + 0.5);
		
		System.out.println(answer);
	}
}

두 방법 시간 차이 (위 두 번째, 아래  첫 번째)

 

두번째가 훨씬 효율적인 방법임을 알 수 있다.

📍 기억할 것

이런 입력이 큰 수에서는 countingSort가 항상 제일 최고의 시간복잡도를 보여주는 것 같다.

반응형