인생은 고통의 연속

Statistics from a Large Sample 본문

프로그래밍/알고리즘

Statistics from a Large Sample

gnidoc 2022. 1. 17. 22:07
    반응형

    https://leetcode.com/problems/statistics-from-a-large-sample/

     

    Statistics from a Large Sample - LeetCode

    Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

    leetcode.com

    256 길이의 List를 주고
    List의 item에서 index값은 값이고 value는 그 값의 갯수를 의미한다

    [0,1,2,1] = 1이 1개, 2가 2개, 3이 1개란 뜻

    이 List를 가지고 아래 5가지의 경우를 구하면 된다

    • minimum : 최소값
    • maximun : 최대값
    • mean : 평균
    • median : 중앙값. List의 갯수가 홀수면 List의 가운데 값, 짝수면 List의 가운데값 2개의 평균
    • mode : 빈도수가 가장 많은 값

    여기까지 보고 별거 아니네하고 풀었다가 생각보다 고전했다...

    함정은 바로 median이었는데 처음엔 값들의 중앙값으로 생각해서 [0,100,2,1]일때 값이 1,2,3뿐이니깐 중앙값을 2로 생각하고 접근했다

    하지만 이 문제에서 원하는 중앙값은 index 에 대한 갯수들까지 고려해야하므로 [0,100,2,1]라면 1이 나와야한다

    사실 테스트케이스를 생각하고 코드를 짰다면 아래처럼 안나오긴했을거 같은데 너무 또 덕지덕지 짜버렸다

    내 정답은 아래와 같다

    class Solution:
        def sampleStats(self, count: List[int]) -> List[float]:
            minimum = -1
            maximum = -1
            mean = 0
            median = 0
            total_count = 0
            mode = (0, 0) # value, count
            
            for k, k_count in enumerate(count):
                if k_count == 0:
                    continue
                    
                if minimum == -1 or k < minimum:
                    minimum = k
                if maximum == -1 or k > maximum:
                    maximum = k
                mean = mean + k * k_count
                total_count = total_count + k_count
                    
                if mode[1] < k_count:
                    mode = (k, k_count)
                
            mean = mean / total_count
            
            middle = int(total_count / 2)
            is_odd = bool(total_count % 2 == 1)
            before_k = -1
            
            for k, k_count in enumerate(count):
                if k_count == 0:
                    continue
                
                if is_odd:
                    if middle == 0:
                        median = k
                        break
                    if middle < 0:
                        median = before_k
                        break
                if not is_odd:
                    if middle == 0:
                        median = (before_k + k) / 2
                        break
                    if middle < 0:
                        median = before_k
                        break
                middle = middle - k_count
                before_k = k
            
            return [float(minimum), float(maximum), mean, median, mode[0] / 1]

    그런데 처음엔 결과적으론 O(n)으로 끝나는 문제라서 속도는 상관없겠다란 생각에
    메모리를 생각 안하고 중앙값 계산할때 아래처럼 무식하게 찾았다

    results = []
    for k, v in count:
        results.extends([k] * v)
    m = int(results.length / 2)
    if results.length % 2 == 1:
    	median = results[m]
    else:
        median = (results[m - 1] + results[m]) / 2

    문제가 뭐냐면 count의 길이는 256으로 고정이지만 위의 방식을 따른다면
    count 의 item의 value만큼 더 List의 크기가 늘어나기 때문에 메모리 문제가 발생한다

    그래서 내가 생각한 방법은
    위 코드에서 results의 index 중간값인 m(=middle)을 구하고
    count를 돌면서 item의 value를 빼는 방식으로 구현했다

    [0, 4, 3, 2, 2] 이라면 m = 5 이고
    item의 index가 1일때 4를 빼서 m = 1
    index가 2일때 3을 빼면 m = -2
    => 이때 2가 중앙값

    다만 이 경우엔 케이스가 매우 많다는 문제가 있다

    홀수인 경우, 
    [0, 1, 3, 1] : 중앙값이 여러개인 경우(3 -> 2 -> -1)
    [0, 1, 1, 1] : 중앙값이 1개인 경우(2 -> 1 -> 0)

    짝수인 경우,
    [0, 1, 2, 1] : 중앙값이 여러개인 경우(2 -> 1 -> -1)
    [0, 2, 1, 1] : 중앙값이 1개인 경우(2 -> 0)

    또 문제는 짝수인 경우는 index가 m-1, m인걸 따로 계산해야되는데
    m-1이 이전 값일수도 있고 현재 값일 수도 있다
    [0,1,1,1,1] : 중앙값은 (2+3)/2 = 2.5
    [0,1,2,1] : 중앙값은 (2+2)/2 = 2

    요것까지 고려해서 코드에 반영했더니...아름다운 if문 떡칠이 발생했다 ^^
    뭐 직관적인게 좋은거니깐 + 정답이니깐 ㅎㅎ
    (속도도 나름 상위권인듯?)

     

    반응형

    '프로그래밍 > 알고리즘' 카테고리의 다른 글

    Goal Parser Interpretation  (0) 2022.02.22
    Sum of Subarray Minimums  (0) 2022.02.22
    Merge Two Sorted Lists  (0) 2022.01.11
    Rearrange Spaces Between Words  (0) 2021.04.26
    two sum  (0) 2021.04.22
    Comments