[C언어] 백준 2108 : 통계학

34087 단어 C백준수정필요C

생각의 흐름

  1. 산술평균 -> sum = sum + arr[i] 로 sum에 다 저장한 뒤 sum / n하면 되겠구나 소수점 자리를 신경써줘야하니 double을 쓰겠네. 소수점자리수는 검색을 해보자.
  2. 중앙값 -> 음 선택정렬로 오름차순 사용하고, n / 2 하면 중앙값이니 그걸 출력해야겠다.
  3. 최빈값 -> 하루종일 고민했음. 일단 가장 많이 나온값을 출력을 먼저 해보고, 두번째인 경우는 나중에 고민해보자.
  4. 범위 -> 선택정렬한걸 arr[0]과 arr[n - 1]의 차이를 해주면 범위가 나오겠구나.

내가 처음에 푼 풀이 (틀림)

#include <stdio.h>

int ft_rep(int arr[], int n)
{
    int i;
    int rep[8001];
    int max, mode = 0;
    i = 0;
    while (i < n)
    {
        rep[arr[i]]++; // rep에 arr[i]를 집어넣고 ++로 세줌
        i++;
    }
    max = 0;
    i = 0;
    while (i < n)
    {
        if (rep[arr[i]] > max)
        {
            max = rep[arr[i]];
            mode = arr[i]; // max값 찾고, 그 지점 mode로 저장
        }
        i++;
    }
    return mode;
}

int ft_aver(int arr[], int n)
{
    int i;
    int sum = 0;
    i = 0;
    while (i < n)
    {
        sum = sum + arr[i];
        i++;
    }
    return sum;
} // sum을 계산

void ft_swap(int arr[], int i, int j)
{
    int temp;
    temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

void ft_sort(int arr[], int n) // 선택정렬
{
    int i, j;
    i = 0;
    while (i < n - 1)
    {
        j = i + 1;
        while (j < n)
        {
            if (arr[i] > arr[j])
                ft_swap(arr, i, j);
            j++;
        }
        i++;
    }
}

int main()
{
    int n, i;
    scanf("%d", &n);
    i = 0;
    int arr[n];
    double dsum;
    while (i < n)
    {
        scanf("%d", &arr[i]);
        i++;
    }
    
    dsum = ft_aver(arr , n);
    dsum = dsum / n;
    printf("%.0f\n", dsum); // 1번
    ft_sort(arr, n);
    printf("%d\n", arr[n / 2]); // 2번
    printf("%d\n", ft_rep(arr, n));
    printf("%d\n", arr[n - 1] - arr[0]); // 4번
    i = 0;
}

여기까지 했는데 최빈값이 도저히 어떻게 풀어야할지 모르겠다.
결국 구글링으로 답을 봤는데도, 이해가 되지 않았다. 너무 지쳤다.

아 그리고 선택정렬을 사용하면 시간초과가 난다고 한다.
내일은 퀵정렬(내장함수)을 공부하고, 다시 최빈값을 이해하는걸 목표로 해야겠다.

다음 날 1,2,4만 출력

#include <stdio.h>
#include <stdlib.h>

int arr[500001];

int compare(const void *a, const void *b)
{
    int num1 = *(int *)a;
    int num2 = *(int *)b;

    if (num1 < num2)
        return -1;
    if (num1 > num2)
        return 1;
    return 0;
}

int main()
{
    int i, n;
    int sum = 0;
    scanf("%d", &n);
    i = 0;
    while (i < n)
    {
        scanf("%d", &arr[i]);
        sum = sum + arr[i];
        i++;
    }
    qsort(arr, n, sizeof(int), compare);
    printf("%.0f\n", sum / (double)n);
    printf("%d\n", arr[n / 2]);
    printf("%d\n", arr[n - 1] - arr[0]);
}

최빈값을 제외한 풀이는 정말 짧다.

최빈값을 포함한 풀이

#include <stdio.h>
#include <stdlib.h>

int arr[500001];
int count[8001];

int compare(const void *a, const void *b)
{
    int num1 = *(int *)a;
    int num2 = *(int *)b;

    if (num1 < num2)
        return -1;
    if (num1 > num2)
        return 1;
    return 0;
}

int maxFinder(int arr[], int size_arr)
{
    int max = arr[0];
    int i = 0;
    while (i < size_arr)
    {
        if (max < arr[i])
            max = arr[i];
        i++;
    }
    return max;
}

int main()
{
    int i, n;
    int sum = 0, mode = 0, flag = 0;
    scanf("%d", &n);
    i = 0;
    while (i < n)
    {
        scanf("%d", &arr[i]);
        sum = sum + arr[i];
        count[arr[i] + 4000]++;
        i++;
    }
    i = 0;
    while (i < 8001)
    {
        if (maxFinder(count, 8001) == count[i])
        {
            flag++;
        }
        i++;
    }
    i = 0;
    while (i < 8001)
    {
        if (flag == 1)
        {
            if (maxFinder(count, 8001) == count[i])
            {
                mode = i - 4000;
                break;
            }
        }
        else
        {
            if (maxFinder(count, 8001) == count[i])
            {
                if (flag == 0)
                {
                    mode = i - 4000;
                    break;
                }
                else
                    flag = 0;
            }
        }
        i++;
    }
    qsort(arr, n, sizeof(int), compare);
    printf("%.0f\n", sum / (double)n);
    printf("%d\n", arr[n / 2]);
    printf("%d\n", mode);
    printf("%d\n", arr[n - 1] - arr[0]);
}

https://mjeong9316.tistory.com/172 여기에서 도움을 받았다.
간단하게 설명하자면, 절대값이 4000을 넘지 않기에 8001로 설정했다. 그 이유는 최대값을 설정할때, 음수일경우 값이 꼬여버리기 때문이다.
그래서 i가 0~ 8000까지 다 돌아가면서, +4000으로 음수를 다 양수로 바꾸어버린 뒤 최빈값을 찾는다.
그리고 max값을 찾으면 flag를 설정해준다.
flag 가 1이면, 제일 큰 값이 하나밖에 없기에 그 값을 처음에 더했던 4000을 뺀 뒤 출력한다. 1보다 크다면 최빈값이 여러개라는 뜻이고, 처음 max값이 등장하면 flag = 0으로 하고, 두번째로 작은 최빈값을 출력하는 것이기에 두번째 max값이 등장하면 flag == 0에 걸리므로 break.

근데 이 코드를 제출하면 85%에서 틀린다. 계속 비교해보면서 아예 같은 코드를 넣어도 봤는데 계속 틀렸다. 한 8번 시도한 것 같은데.. 어디서 틀렸는지 이해가 되지 않는다.

최종 제출 코드

https://sedangdang.tistory.com/19
그냥 이사람꺼 카피했다..

논리도 비교해봤는데 도저히 어디가 문제가 되는지 모르겠다..

일단 즐겨찾기 해놨으니 다음에 다시 봐야할 것 같다.. 이 문제에 시간을 얼마나 갈았는지 모르겠다

확실히 음수를 다 양수로 바꿔버린 다음에 나중에 그 값을 빼는 아이디어는 정말 좋긴 했다.
또한 반올림을 double형으로 하지 않고 int형에서 각각 0.5씩 넣어서 처리하는 방법은 신기했다.

좋은 웹페이지 즐겨찾기