Dandy Now!
  • [알고리즘][파이썬] 백준_2108_통계학
    2021년 12월 16일 15시 25분 25초에 업로드 된 글입니다.
    작성자: DandyNow
    728x90
    반응형

    https://www.acmicpc.net/problem/2108

     

    2108번: 통계학

    첫째 줄에 수의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 단, N은 홀수이다. 그 다음 N개의 줄에는 정수들이 주어진다. 입력되는 정수의 절댓값은 4,000을 넘지 않는다.

    www.acmicpc.net

    N개의 입력 값으로

    산술평균, 중앙값, 최빈값, 범위를 출력해야 한다.

    제출 결과 "시간 초과"로 매우 고생했다.

    범인은 최빈값!


    시간 초과(리스트 count 메소드 사용)

    # 최빈값 구할 때 for문 사용하여 값의 빈도수(cnt) 구함(결과: 시간 초과)
    import sys
    
    N = int(sys.stdin.readline())
    
    nums = []
    for _ in range(N):
        nums.append(int(sys.stdin.readline()))
    
    # 산술평균
    avg = round(sum(nums) / N)
    print(avg)
    
    # 중앙값
    nums.sort()
    mid = nums[int(N / 2)]
    print(mid)
    
    # 최빈값
    mode = []
    tmp = 0
    for i in nums:
        # for문 대신 cnt를 구할 때 nums.count(i)도 사용했으나 "시간 초과" 해결 안됨
        cnt = 0
        for j in nums:
            if i == j:
                cnt += 1
        if tmp == cnt:
            mode.append(i) 
        elif cnt > tmp:
            tmp = cnt
            mode = []
            mode.append(i)
    
    lst = list(set(mode))
    lst.sort()
    if len(lst) > 1:
        print(lst[1])
    else:
        print(lst[0])
    
    # 범위
    dist = nums[-1] - nums[0]
    print(dist)

     

    최빈값에서 값의 빈도수(cnt)를 구할 때,

    먼저 리스트의 count 메소드를 이용했었다.

    cnt = nums.count(i)

    결과는 시간 초과!

     

    그 다음으로는 for문을 이용,

    cnt에 +1 해주었다(위 코드 참조).

    결과는 시간 초과!


    최종 제출코드

    # collections 모듈의 Counter 클래스 사용(결과: 맞았습니다!)
    import sys
    from collections import Counter
    
    N = int(sys.stdin.readline())
    
    nums = []
    for _ in range(N):
        nums.append(int(sys.stdin.readline()))
    
    # 산술평균
    avg = round(sum(nums) / N)
    print(avg)
    
    # 중앙값
    nums.sort()
    mid = nums[int(N / 2)]
    print(mid)
    
    # 최빈값
    mode = []
    nums.sort()
    mode = Counter(nums).most_common()
    if len(mode) > 1 and mode[0][1] == mode[1][1]:
        print(mode[1][0])
    else:
        print(mode[0][0])
    
    # 범위
    dist = nums[-1] - nums[0]
    print(dist)

     

    구글링 해보니 대부분 collections 모듈의 Counter 클래스로 문제 해결했다.

    간단하게 Counter 클래스의 사용법을 익히고 코드에 적용했다.

    Counter 클래스를 사용하면 리스트에 튜플이 담긴 값을 얻을 수 있다.

    [(값1, 개수), (값2, 개수), (값n, 개수)]

     

    처음 최빈값 코드를 작성할 때 위 리스트와 같은 구조의 값을 만들기 위해 고민했는데,

    그 때는 딕셔너리만 생각했었다.

    딕셔너리는 index 값을 적용할 수가 없어 점점 하드코딩이 되어 갔었다.

    결국 다른 방법으로 풀이해 제출 했는데 결과는 시간 초과!

    Counter 클래스가 딱 원했던 기능이다!

    728x90
    반응형
    댓글