실습 - Go/백준

2108 - 통계학 (Golang)

개발참치 2021. 7. 27.

문제

수를 처리하는 것은 통계학에서 상당히 중요한 일이다.

통계학에서 N개의 수를 대표하는 기본 통계값에는 다음과 같은 것들이 있다. 단, N은 홀수라고 가정하자.

  1. 산술평균 : N개의 수들의 합을 N으로 나눈 값
  2. 중앙값 : N개의 수들을 증가하는 순서로 나열했을 경우 그 중앙에 위치하는 값
  3. 최빈값 : N개의 수들 중 가장 많이 나타나는 값
  4. 범위 : N개의 수들 중 최댓값과 최솟값의 차이

N개의 수가 주어졌을 때, 네 가지 기본 통계값을 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다.

그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.

 

예제 입력

5
1
3
8
-2
2

출력

첫째 줄에는 산술평균을 출력한다. 소수점 이하 첫째 자리에서 반올림한 값을 출력한다.

둘째 줄에는 중앙값을 출력한다.

셋째 줄에는 최빈값을 출력한다. 여러 개 있을 때에는 최빈값 중 두 번째로 작은 값을 출력한다.

넷째 줄에는 범위를 출력한다.

 

예제 출력

2
2
1
10

 

분석

언뜻 문제만 보면 쉽게 느껴질 수 있으나, 함정이 많은 문제로 보입니다.

첫번째 산술평균만 해도 자료형이 정확해야하며 ( int 형으로 제출 시 오답 처리 )

세번째 최빈값을 배열로 푼다면 0이 있다는 사실을 기억해야 합니다. ( -4000 ~ 4000 = 8001의 배열 크기 필요 )

 

풀이

 

2108 - 통계학 (Golang) - 풀이
GoLand 캡쳐

우선 입력값들을 받은 뒤 배열을 복사하여 중앙값 계산을 위한 복사 배열을 만들어 줍니다

또한 나올 수 있는 최대값과 최소값을 산정하여

반복문으로 최대값과 최소값, 모두의 합친 값을 구해주고

 

전체 합친값을 형변환 해주어 배열의 길이만큼 나눠준 산술평균을 구해줍니다. 

위의 복사 배열은 정렬이 되어있으므로 이 것의 /2는 곧 중앙 값이라고 볼 수 있습니다.

최빈값은 따로 함수로 구성을 하였는데

 

 

 

2108 - 통계학 (Golang) - 풀이
최빈값 찾는 함수 캡쳐

우선 배열의 첫번째 인자를 비교값에 넣어주고 

숫자를 세는 변수, 최대 숫자를 세는 변수를 선언해줍니다.

 

배열의 두번째 인자부터 반복문을 통해 인자가 같으면 counter (숫자를 세는 변수)를 +1해줍니다

 

또한 이 counter가 maxCounter와 같고 modes(비교값 배열)에 인자가 하나라면 modes에 추가해줍니다

maxCounter 보다 크다면 maxCounter (최대값)이 이 counter로 교체되고 modes도 이 인자하나를 가지는 배열로 초기화 됩니다.

 

만일 modes (비교값 배열)에 첫번째 인자 외에 다른 인자가 포함되있으면 제일 최빈값이므로 이것을 반환해주고 

아니면 첫번째 인자가 최빈값이 됩니다.

 

소스 코드

package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"sort"
	"strconv"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Scan()

	var length, _ = strconv.Atoi(scanner.Text())
	numberArray := make([]int, length)
	sortArray := make([]int, length)

	for i := 0; i < length; i++ {
		scanner.Scan()
		numberArray[i], _ = strconv.Atoi(scanner.Text())
	}
	copy(sortArray, numberArray)
	sort.Ints(sortArray)

	var sum = 0
	var max = -4000
	var min = 4000

	for i := 0; i < length; i++ {
		sum += numberArray[i]
		if numberArray[i] > max {
			max = numberArray[i]
		}
		if numberArray[i] < min {
			min = numberArray[i]
		}
	}

	fmt.Println(math.Round(float64(sum) / float64(length)))
	fmt.Println(sortArray[length/2])
	fmt.Println(findMode(sortArray))
	fmt.Println(max - min)
}

func findMode(a []int) int {
	prevN := a[0]
	counter := 0

	modes := []int{prevN}
	maxCounter := 0

	for _, n := range a[1:] {
		if prevN != n {
			prevN = n
			counter = 0
		} else {
			counter++
		}

		if counter == maxCounter {
			if len(modes) < 2 {
				modes = append(modes, n)
			}
		} else if counter > maxCounter {
			maxCounter = counter
			modes = []int{n}
		}
	}

	if len(modes) > 1 {
		return modes[1]
	}
	return modes[0]
}

 

'실습 - Go > 백준' 카테고리의 다른 글

9498 - 시험 성적 (Golang)  (0) 2021.07.29
1330 - 두 수 비교하기 (Golang)  (0) 2021.07.29
2588 - 곱셈 (Golang)  (0) 2021.07.07
10430 - 나머지 (Golang)  (0) 2021.07.07
10869 - 사칙 연산 (Golang)  (0) 2021.07.07

댓글