오늘은 백준 2108번 통계학 문제를 풀어봤다.
입력으로 주어진 숫자들을 통해 산술 평균, 중앙값, 최빈값, 범위를 구하는 문제다.

https://www.acmicpc.net/problem/2108
문제 이해
N개의 수가 주어지고, 이 숫자들로 다음 네 가지 값을 출력해야 한다.
산술 평균 (소수 첫째 자리에서 반올림)
중앙값
최빈값 (여러 개면 두 번째로 작은 값)
범위 (최댓값 - 최솟값)
풀이 과정
int n = int.Parse(Console.ReadLine());
int[] nums = new int[n];
for (int i = 0; i < n; i++)
nums[i] = int.Parse(Console.ReadLine());
Array.Sort(nums);
Average() 함수로 평균을 구한 뒤, Math.Round()로 소수 첫째 자리에서 반올림했다.MidpointRounding.AwayFromZero를 넣어줘야 0.5는 무조건 올림으로 처리된다.double avg = nums.Average();
Console.WriteLine((int)Math.Round(avg, MidpointRounding.AwayFromZero));
Console.WriteLine(nums[n / 2]);
Dictionary<int, int>를 사용해서 각 숫자의 등장 횟수를 저장했다.Dictionary<int, int> freq = new Dictionary<int, int>();
foreach (int num in nums)
{
if (freq.ContainsKey(num))
freq[num]++;
else
freq[num] = 1;
}
int maxFreq = freq.Values.Max();
List<int> modes = freq.Where(kv => kv.Value == maxFreq)
.Select(kv => kv.Key)
.ToList();
modes.Sort();
Console.WriteLine(modes.Count > 1 ? modes[1] : modes[0]);
주의할 점은, 최빈값이 여러 개면 두 번째로 작은 값을 출력해야 한다는 것.
Console.WriteLine(nums[n - 1] - nums[0]);
작성한 코드
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
int n = int.Parse(Console.ReadLine());
int[] nums = new int[n];
for (int i = 0; i < n; i++)
nums[i] = int.Parse(Console.ReadLine());
Array.Sort(nums);
// 산술 평균
Console.WriteLine((int)Math.Round(nums.Average(), MidpointRounding.AwayFromZero));
// 중앙값
Console.WriteLine(nums[n / 2]);
// 최빈값
Dictionary<int, int> freq = new Dictionary<int, int>();
foreach (int num in nums)
{
if (freq.ContainsKey(num))
freq[num]++;
else
freq[num] = 1;
}
int maxFreq = freq.Values.Max();
List<int> modes = freq.Where(kv => kv.Value == maxFreq)
.Select(kv => kv.Key)
.ToList();
modes.Sort();
Console.WriteLine(modes.Count > 1 ? modes[1] : modes[0]);
// 범위
Console.WriteLine(nums[n - 1] - nums[0]);
}
}
느낀 점
처음엔 최빈값 조건이 조금 까다롭게 느껴졌는데, Dictionary를 쓰고 나니 깔끔하게 해결됐다.
평균을 반올림할 때도 그냥 Round()만 쓰면 반올림 방향이 기대와 다를 수 있어서 MidpointRounding.AwayFromZero를 꼭 써야 한다는 걸 배웠다.