<문제 제시>
<문제설명>
수를 처리하는 것은 통계학에서 상당히 중요한 일이다.
통계학에서 N개의 수를 대표하는 기본 통계값에는 다음과 같은 것들이 있다.
단, N은 홀수라고 가정하자.
산술평균 : N개의 수들의 합을 N으로 나눈 값
중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값
최빈값 : N개의 수들 중 가장 많이 나타나는 값
범위 : N개의 수들 중 최댓값과 최솟값의 차이
N개의 수가 주어졌을 때, 네 가지 기본 통계값을 구하는 프로그램을 작성하시오.
<예시 입출력>
<문제 해결 과정>
요구하는 산술평균, 중앙값, 최빈값, 범위를 구하는 문제이다. 나머지는 간단한 연산으로 구할 수 있다고 해도 최빈값을 구하는 부분에서 생각이 많아졌다.
Try 1)
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int[] arr = new int[N];
int sum = 0;
for(int i = 0; i < N; i++) {
arr[i] = Integer.parseInt(br.readLine());
sum += arr[i];
}
// 1차 테스트 출력
System.out.println(Arrays.toString(arr));
// 1. 산술평균 구하기
int ave = sum / N;
System.out.println("산술평균 = " + ave);
// 3. 최빈값 구하기
int num = 0;
int[] test = new int[8001];
for(int i = 0; i < 8001; i++) {
for(int j = 0; j < arr.length; i++) {
if(!test[i]) {
int data = arr[j];
test[data] = true;
}
else {
num = i;
}
}
}
System.out.println("최빈값 = " + num);
// 2. 중앙값 구하기
int mid = 0;
Arrays.sort(arr);
mid = arr[N / 2];
System.out.println("중앙값 = " + mid);
// 4. 범위 구하기
int ran = arr[arr.length - 1] - arr[0];
System.out.println("범위 = " + ran);
boolean배열로 최빈값을 찾으려했으나, 인덱스 범위 오류가 발생하였다.
Answer 1)
// 3. 최빈값 구하기
int num = 0;
int[] test = new int[8001];
////
int[] plus = new int[4002];
int[] minus = new int[4001];
for(int i = 0; i < N; i++) {
// 값이 음수일 경우, 절대값을 해준 후 minus배열에 체크
if(arr[i] < 0) {
minus[Math.abs(arr[i])]++;
}
else {
plus[arr[i]]++;
}
}
List<Integer> list = new ArrayList<>();
// 가장 높은 빈도수를 갱신
int max = 0;
for(int i = 0;i < plus.length; i++) {
max = Math.max(max, plus[i]);
}
for(int i = 0;i < minus.length; i++) {
max = Math.max(max, minus[i]);
}
for(int i : arr) {
// 값이 음수일 경우
if(i < 0) {
// 값을 절대값처리한 것이 max에 담은 값과 같고, 리스트에서도 i를 포함하고 있지 않으면,
if(minus[Math.abs(i)] == max && !(list.contains(i))) {
list.add(i);
}
}
else {
if(plus[Math.abs(i)] == max && !(list.contains(i))) {
list.add(i);
}
}
}
// 만약 최빈값이 두개이상으로 겹친다면, 2번째로 작은 것을 출력
if(list.size() >= 2) {
num = list.get(1);
}
else {
num = list.get(0);
}
System.out.println("최빈값 = " + num);
먼저 입력되는 값의 범위가 주어졌기 때문에 반을 나누어 양수부분과 음수부분의 배열로 나눈다.
값이 음수이면 그 해당하는 값을 절대값해준 후 음수 배열에 ++ (개수체크)해주면 해당 값의 인덱스 위치에 따라
값이 증가한다. else문으로는 양수 배열에 추가해준다.
Math.max로 plus와 minus 배열에서의 개수가 가장 많은 값을 체크한다. (최빈값 유력)
for-each문으로 처음 값들을 가져와 음수일 경우
1) 그 가져온 값을 절대값 체크한 것과 max가 같고
2) 리스트에서도 가져온 값을 포함하고 있지 않으면 (contains() 사용)
>> 리스트에 추가한다.
- 만약 최빈값이 2개 이상 (ex. 3, 3) 으로 겹친다면,
>> list.size() >= 2 로 체크가능 (=최빈값을 담은 리스트의 크기가 2이상이면 최빈값이 2개 이상인 것)
>> list.get(1)로 두번째로 작은 값을 출력
>> else { num = list.get(0) };
<전체코드>
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int[] arr = new int[N];
double sum = 0;
for(int i = 0; i < N; i++) {
arr[i] = Integer.parseInt(br.readLine());
sum += arr[i];
}
// 1차 테스트 출력
System.out.println(Arrays.toString(arr));
// 1. 산술평균 구하기
double ave = Math.round((double)sum / N);
System.out.println("산술평균 = " + (int)ave);
// 2. 중앙값 구하기
int mid = 0;
Arrays.sort(arr);
mid = arr[N / 2];
System.out.println("중앙값 = " + mid);
// 3. 최빈값 구하기
int num = 0;
int[] test = new int[8001];
////
int[] plus = new int[4002];
int[] minus = new int[4001];
for(int i = 0; i < N; i++) {
// 값이 음수일 경우, 절대값을 해준 후 minus배열에 체크
if(arr[i] < 0) {
minus[Math.abs(arr[i])]++;
}
else {
plus[arr[i]]++;
}
}
List<Integer> list = new ArrayList<>();
// 가장 높은 빈도수를 갱신
int max = 0;
for(int i = 0;i < plus.length; i++) {
max = Math.max(max, plus[i]);
}
for(int i = 0;i < minus.length; i++) {
max = Math.max(max, minus[i]);
}
for(int i : arr) {
// 값이 음수일 경우
if(i < 0) {
// 값을 절대값처리한 것이 max에 담은 값과 같고, 리스트에서도 i를 포함하고 있지 않으면,
if(minus[Math.abs(i)] == max && !(list.contains(i))) {
list.add(i);
}
}
else {
if(plus[Math.abs(i)] == max && !(list.contains(i))) {
list.add(i);
}
}
}
// 만약 최빈값이 두개이상으로 겹친다면, 2번째로 작은 것을 출력
if(list.size() >= 2) {
num = list.get(1);
}
else {
num = list.get(0);
}
System.out.println("최빈값 = " + num);
// 4. 범위 구하기
int ran = arr[arr.length - 1] - arr[0];
System.out.println("범위 = " + ran);
// 최종 출력
System.out.println((int)ave);
System.out.println(mid);
System.out.println(num);
System.out.println(ran);
}
}
최빈값을 구하는 부분이 핵심인 문제였다. 하지만 최빈값에서도 최빈값이 2개이상이라는 조건과 같이 예외사항이 분명 존재하기때문에 모두 만족하는 코드를 작성하는 것이 목표였다.
문제링크)
https://www.acmicpc.net/problem/2108
'Algorithms > 백준' 카테고리의 다른 글
[백준] '좌표 압축' - Java (0) | 2023.07.19 |
---|---|
[백준] '좌표 정렬하기' - Java (0) | 2023.07.18 |
[백준] '수 정렬하기3' - Java (0) | 2023.07.17 |
[백준] '색종이' - Java (0) | 2023.07.17 |
[백준] '최댓값' - Java (0) | 2023.07.16 |