μ•Œκ³ λ¦¬μ¦˜ 문제/BOJ_Java

[BOJ/Step12] 2108 : 톡계학 (JAVA)

NaNaRinπŸ™ƒ 2021. 1. 30. 22:09

www.acmicpc.net/problem/2108

 

2108번: 톡계학

첫째 쀄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진닀. κ·Έ λ‹€μŒ N개의 μ€„μ—λŠ” μ •μˆ˜λ“€μ΄ 주어진닀. μž…λ ₯λ˜λŠ” μ •μˆ˜μ˜ μ ˆλŒ“κ°’μ€ 4,000을 λ„˜μ§€ μ•ŠλŠ”λ‹€.

www.acmicpc.net


문제

수λ₯Ό μ²˜λ¦¬ν•˜λŠ” 것은 ν†΅κ³„ν•™μ—μ„œ μƒλ‹Ήνžˆ μ€‘μš”ν•œ 일이닀. ν†΅κ³„ν•™μ—μ„œ N개의 수λ₯Ό λŒ€ν‘œν•˜λŠ” κΈ°λ³Έ ν†΅κ³„κ°’μ—λŠ” λ‹€μŒκ³Ό 같은 것듀이 μžˆλ‹€. 단, N은 ν™€μˆ˜λΌκ³  κ°€μ •ν•˜μž.

- μ‚°μˆ ν‰κ·  : N개의 μˆ˜λ“€μ˜ 합을 N으둜 λ‚˜λˆˆ κ°’

- 쀑앙값 : N개의 μˆ˜λ“€μ„ μ¦κ°€ν•˜λŠ” μˆœμ„œλ‘œ λ‚˜μ—΄ν–ˆμ„ 경우 κ·Έ 쀑앙에 μœ„μΉ˜ν•˜λŠ” κ°’

- μ΅œλΉˆκ°’ : N개의 μˆ˜λ“€ 쀑 κ°€μž₯ 많이 λ‚˜νƒ€λ‚˜λŠ” κ°’

- λ²”μœ„ : N개의 μˆ˜λ“€ 쀑 μ΅œλŒ“κ°’κ³Ό μ΅œμ†Ÿκ°’μ˜ 차이

N개의 μˆ˜κ°€ μ£Όμ–΄μ‘Œμ„ λ•Œ, λ„€ 가지 κΈ°λ³Έ 톡계값을 κ΅¬ν•˜λŠ” ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜μ‹œμ˜€.

 

μž…λ ₯

첫째 쀄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진닀. κ·Έ λ‹€μŒ N개의 μ€„μ—λŠ” μ •μˆ˜λ“€μ΄ 주어진닀. μž…λ ₯λ˜λŠ” μ •μˆ˜μ˜ μ ˆλŒ“κ°’μ€ 4,000을 λ„˜μ§€ μ•ŠλŠ”λ‹€.

 

좜λ ₯

첫째 μ€„μ—λŠ” μ‚°μˆ ν‰κ· μ„ 좜λ ₯ν•œλ‹€. μ†Œμˆ˜μ  μ΄ν•˜ 첫째 μžλ¦¬μ—μ„œ λ°˜μ˜¬λ¦Όν•œ 값을 좜λ ₯ν•œλ‹€.

λ‘˜μ§Έ μ€„μ—λŠ” 쀑앙값을 좜λ ₯ν•œλ‹€.

μ…‹μ§Έ μ€„μ—λŠ” μ΅œλΉˆκ°’μ„ 좜λ ₯ν•œλ‹€. μ—¬λŸ¬ 개 μžˆμ„ λ•Œμ—λŠ” μ΅œλΉˆκ°’ 쀑 두 번째둜 μž‘μ€ 값을 좜λ ₯ν•œλ‹€.

λ„·μ§Έ μ€„μ—λŠ” λ²”μœ„λ₯Ό 좜λ ₯ν•œλ‹€.

 

예제 μž…λ ₯ 1

5

1

3

8

-2

2

 

예제 좜λ ₯ 1

2

2

1

10

 

예제 μž…λ ₯ 2

1

4000

 

예제 좜λ ₯ 2

4000

4000

4000

0

 

예제 μž…λ ₯ 3

5

-1

-2

-3

-1

-2

 

예제 좜λ ₯ 3

-2

-2

-1

2


풀이

μ‚°μˆ ν‰κ· κ³Ό 쀑앙값, μ΅œλΉˆκ°’, λ²”μœ„λ₯Ό κ΅¬ν•˜λŠ” 문제

=> μΉ΄μš΄νŒ… μ •λ ¬ μ•Œκ³ λ¦¬μ¦˜ 이용

 

μ‚°μˆ ν‰κ· μ€ μž…λ ₯받은 값을 λͺ¨λ‘ 더해 개수둜 λ‚˜λˆ„λ©΄ 되고

쀑앙값은 μ •λ ¬ ν›„ n/2 자리의 값이며

λ²”μœ„λŠ” μ •λ ¬ ν›„ λ§ˆμ§€λ§‰ κ°’ - 첫번째 값이닀.

μ΅œλΉˆκ°’μ΄ κ°€μž₯ κΉŒλ‹€λ‘­λ‹€. μ΅œλΉˆκ°’μ΄ μ—¬λŸ¬κ°œ 일 λ•Œ 두 번째둜 μž‘μ€ 값을 좜λ ₯ν•΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

 

1. n개의 μ •μˆ˜λ₯Ό μž…λ ₯λ°›λŠ”λ‹€.

   1-1. μ΄λ•Œ μž…λ ₯λ°›μ•„ 배열에 μ €μž₯함과 λ™μ‹œμ— total λ³€μˆ˜μ— 더해 총 합을 ꡬ해주고,

   1-2. μž…λ ₯λ°›λŠ” 값을 λΉ„κ΅ν•˜μ—¬ μ΅œλŒ“κ°’κ³Ό μ΅œμ†Ÿκ°’μ„ maxκ°’κ³Ό mix값에 μ €μž₯ν•œλ‹€.

 

2. μ‚°μˆ ν‰κ· κ³Ό λ²”μœ„λ₯Ό κ΅¬ν•œλ‹€

   2-1. μž…λ ₯이 λλ‚˜λ©΄ total을 n으둜 λ‚˜λˆ„μ–΄ μ‚°μˆ ν‰κ· μ„ ꡬ해쀀닀.

           μ£Όμ˜ν•  점은 total을 double ν˜•μœΌλ‘œ μ„ μ–Έν•΄ μ£Όμ–΄μ•Ό n으둜 λ‚˜λˆ„λŠ” κ³Όμ •μ—μ„œ μ†Œμˆ˜μ μ΄ 날아가지 μ•ŠλŠ”λ‹€.

           μ†Œμˆ˜μ  μ²«μ§Έμžλ¦¬μ—μ„œ 반올림 ν•΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— Math.round() λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•œλ‹€.

   2-2. maxκ°’κ³Ό min값을 μ΄μš©ν•΄ λ²”μœ„λ₯Ό ꡬ해쀀닀. (max - min)

 

μΉ΄μš΄νŒ… 정렬을 μ΄μš©ν•΄ μ΅œλΉˆκ°’μ„ κ΅¬ν•΄λ³΄κΈ°λ‘œ ν•œλ‹€.

κΈ°μ‘΄ μΉ΄μš΄νŒ… 정렬은 μƒμˆ˜κ°’λ§Œ μ •λ ¬ν•  수 μžˆμ—ˆμ§€λ§Œ, 이λ₯Ό λ³€ν˜•ν•˜μ—¬ μŒμˆ˜κ°’λ„ 정렬이 κ°€λŠ₯ν•˜λ„λ‘ ν•΄ μ€€λ‹€.

μ•žμ—μ„œ κ΅¬ν•œ min 값을 λ°°μ—΄μ˜ 0, max 값을 λ°°μ—΄μ˜ λ§ˆμ§€λ§‰ μœ„μΉ˜λΌκ³  κ°€μ •, λ²”μœ„+1 크기의 λ°°μ—΄ countλ₯Ό λ§Œλ“€μ–΄ λΉˆλ„μˆ˜λ₯Ό μ…ˆ ν•΄μ£ΌλŠ” 방식을 μ‚¬μš©ν•  것이닀.

예제 1κ³Ό 같이 -2 ~ 8 κΉŒμ§€μ˜ μˆ˜κ°€ 주어진닀면 λ²”μœ„λŠ” 10, 크기 11인 배열을 λ§Œλ“€μ–΄ μΉ΄μš΄νŒ… ν•΄μ€€λ‹€.

 

3. 2-2μ—μ„œ κ΅¬ν•œ λ²”μœ„λ₯Ό μ΄μš©ν•΄ λ²”μœ„+1 크기의 count 배열을 λ§Œλ“€μ–΄ λΉˆλ„μˆ˜λ₯Ό μ €μž₯ν•œλ‹€.

    λΉˆλ„μˆ˜λ₯Ό μ…€ λ•Œ, μΉ΄μš΄νŒ… μ •λ ¬κ³Ό 같이 ν•΄λ‹Ή μˆ«μžμ™€ 같은 λ°°μ—΄ μΈλ±μŠ€μ— μ ‘κ·Όν•  μˆ˜λŠ” μ—†λ‹€. μˆ«μžκ°€ 음수일 μˆ˜λ„ 있기 λ•Œλ¬Έμ΄λ‹€.

    예제 1μ—μ„œλŠ” -2λŠ” λ°°μ—΄[0]에, 8은 λ°°μ—΄[10]에 μ €μž₯될 것이닀. [숫자 - μ΅œμ†Ÿκ°’] 이 ν•΄λ‹Ή 숫자의 μΈλ±μŠ€κ°€ 됨을 μ•Œ 수 μžˆλ‹€.

이제 각 수의 λΉˆλ„μˆ˜λ₯Ό 배열에 μ €μž₯ν•˜μ˜€λ‹€.

 

4. count λ°°μ—΄ 쀑 κ°€μž₯ 큰 값이 뭔지 μ°ΎλŠ”λ‹€. λ‘λ²ˆμ§Έλ‘œ μž‘μ€ μˆ«μžμΈμ§€ 확인할 num, μ΅œλΉˆκ°’μ˜ 인덱슀λ₯Ό μ €μž₯ν•  mode_idx   4-1. μ΅œλΉˆκ°’μ˜ 인덱슀λ₯Ό λ³€μˆ˜ mode_idx에 μ €μž₯ν•œ ν›„ forλ¬Έ μ•ˆμ—μ„œ count 배열을 μˆœνšŒν•˜λ©° λΉ„κ΅ν•œλ‹€.   4-2. if (count[mode_idx] == count[i])일 λ•Œ for문을 νƒˆμΆœν•œ ν›„ κ·Έ 인덱슀λ₯Ό 좜λ ₯ν•˜λ©΄ λ˜κ² λ‹€κ³  μƒκ°ν–ˆλŠ”λ° ν˜Ήμ‹œ κ·Έ μˆ«μžκ°€ μ΅œλΉˆκ°’μ΄ μ•„λ‹ˆλ©΄ μ–΄λ–‘ν•˜μ§€ ν•˜λŠ” 생각이 λ“€μ—ˆλ‹€.           κ·Έλž˜μ„œ 쑰건을 μΆ”κ°€ν–ˆλ‹€. if(count[mode_idx] == count[i] && num == 1)일 λ•Œ, mode_idx = i, num++을 ν•΄μ€€λ‹€.   4-3. if(count[mode_idx] < count[i] && count[mode_idx] != count[i])일 λ•Œ, mode_idx = i, num = 1을 ν•΄μ€€λ‹€.=> 카운트 λ°°μ—΄ 값을 λΉ„κ΅ν•˜κ³ , κ°€μž₯ 큰 κ°’μ˜ μΈλ±μŠ€κ°€ mode_idx 에 μ €μž₯λœλ‹€. κ°€μž₯ 큰 값이 μ€‘λ³΅μœΌλ‘œ λ‚˜μ˜¬ 경우, λ‘λ²ˆμ§Έ κ°’λ§Œ μ €μž₯ν•˜κΈ° μœ„ν•΄μ„œ num이 1일 λ•Œλ§Œ num을 μ¦κ°€μ‹œμΌœμ€€λ‹€. λ˜ν•œ λ°°μ—΄ 뒷뢀뢄에 더 큰 값이 λ‚˜μ˜¬ 수 μžˆμœΌλ―€λ‘œ 더 큰 값을 λ°œκ²¬ν•œ κ²½μš°μ—” num 값을 1둜 λ°”κΏ”μ€€λ‹€.forλ¬Έ μˆ˜ν–‰μ΄ λλ‚˜λ©΄ mode_idx에 μ΅œλΉˆκ°’μ΄ μ €μž₯λ˜μ—ˆμ„ 것이닀. 이λ₯Ό μ΄μš©ν•΄ μ΅œλΉˆκ°’μ„ ꡬ해쀀닀. min값을 더해주어야 ν•œλ‹€.

 

5. count λ°°μ—΄μ˜ λΉˆλ„μˆ˜λ₯Ό λˆ„μ ν•΄μ„œ 더해주고,

 

6. μž…λ ₯ λ°°μ—΄μ˜ μ—­μˆœμœΌλ‘œ λ°°μ—΄b에 μš”μ†Œλ₯Ό μ±„μ›Œλ„£λŠ”λ‹€.    

μ΄λ•Œ, λΉˆλ„μˆ˜λ₯Ό μ…€ λ•Œμ™€ λ§ˆμ°¬κ°€μ§€λ‘œ ν•΄λ‹Ή 숫자 κ·ΈλŒ€λ‘œ λ°°μ—΄ μΈλ±μŠ€μ— μ ‘κ·Όν•˜λ©΄ 였λ₯˜κ°€ λ‚  수 있기 λ•Œλ¬Έμ— 숫자 - μ΅œμ†Ÿκ°’ 으둜 배열에 μ ‘κ·Όν•΄μ•Όλ§Œ ν•œλ‹€.

 

7. λ°°μ—΄ bλ₯Ό κΈ°μ‘΄ 배열에 λ³΅μ‚¬ν•œλ‹€.

 

8. μ •λ ¬λœ λ°°μ—΄[n/2] 에 μœ„μΉ˜ν•œ 쀑앙값을 μ €μž₯

 

9. μ‚°μˆ ν‰κ· κ³Ό 쀑앙값, μ΅œλΉˆκ°’, λ²”μœ„λ₯Ό μ°¨λ‘€λ‘œ 좜λ ₯ν•œλ‹€.

 

import java.io.*;

public class B2108 {

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

		int n = Integer.parseInt(br.readLine());
		int[] sort = new int[n];
		double total = 0;
		
		for(int i = 0; i < n; i++) {
			sort[i] = Integer.parseInt(br.readLine());
			total += sort[i];
		}
		
		int max = sort[0];
		int min = sort[0];
		for(int i = 0; i < n; i++) {
			if(sort[i] > max)
				max = sort[i];
			if(sort[i] < min)
				min = sort[i];
		}
		
		int i1 = (int)Math.round(total / n);	// μ‚°μˆ ν‰κ· 
		int i2 = 0;								// 쀑앙값
		int i3 = 0; 							// μ΅œλΉˆκ°’
		int i4 = max - min;;					// λ²”μœ„
		
		int[] count = new int[i4+1];
		int[] b = new int[n];
		
		for(int i = 0; i < sort.length; i++) {
			count[sort[i] - min]++;
		}
		
		int mode = -1;
		int num = 1;
		int mode_idx = 0;
		for(int i = 0; i < count.length; i++) {
			if(mode == count[i] && num == 1) {
				mode_idx = i;
				num++;
			}
			if(mode < count[i] && mode != count[i]) {
				mode = count[i];
				mode_idx = i;
				num = 1;
			}
		}
		i3 = mode_idx+min;
		
		for(int i = 1; i < i4+1; i++) count[i] += count[i-1];
		for(int i = n-1; i >= 0; i--) b[--count[sort[i] - min]] = sort[i];
		for(int i = 0; i < n; i++) sort[i] = b[i];

		i2 = sort[n/2];				
						
		System.out.println(i1);
		System.out.println(i2);
		System.out.println(i3);
		System.out.println(i4);
	}
}