Archive

[Hackerrank] [Medium] Fraudulent Activity Notifications 본문

공부/Algorithm

[Hackerrank] [Medium] Fraudulent Activity Notifications

mariabeetle 2020. 8. 24. 17:36

https://www.hackerrank.com/challenges/fraudulent-activity-notifications/problem

 

Fraudulent Activity Notifications | HackerRank

Print the number of times a customer receives a notification

www.hackerrank.com

풀이

  • d길이를 유지하면서 median을 유동적으로 계속 구해줘야함.
  • 한 번 iteration할 때마다 sort하고, median을 직접 계산하면 timeout.
  • 문제 조건에서 expenditure[i]는 0 이상 200 이하의 정수임을 명시했기 때문에 이를 count하는 배열을 만들어 median을 구하는데 활용.
    • count[expenditure[i]] = frequency
    • expenditure[i]의 빈도 수를 저장하는 리스트 만듬.
  • d가 홀수일 때, 짝수일 때 median을 구하는 방법이 다름.
    • 리스트가 주어졌을 때,
    • 홀수일 때 : 가운데 index의 값을 반환 ; [a1, a2, a3, a4, a5] -> a3
    • 짝수일 때 : 가운데 두 수의 평균을 반환 ; [a1, a2, a3, a4] -> (a2 + a3) / 2
  • count의 index가 expenditure[i]이기 때문에, 처음 d개로 median을 구하고, 매번 count[expenditure[i - d] ]의 값을 1 감소시킴으로써 median을 구할 때 element개수를 d개로 유지하기 쉬움.
def activityNotifications(expenditure, d):
    def get_median(count, d):
        counting = 0

        if d % 2 == 0:
            mid_1, mid_2 = 0, 0
            for idx, freq in enumerate(count):
                counting += freq
                if mid_1 == 0 and counting >= (d//2):
                    mid_1 = idx
                if mid_2 == 0 and counting >= (d//2 +1):
                    mid_2 = idx
                    return (mid_1+mid_2) / 2
        else:
            for idx, freq in enumerate(count):
                counting += freq
                if counting >= (d // 2) + 1:
                    return idx

    ans = 0
    count = [0]*200
    for idx, spend in enumerate(expenditure):
        if idx < d: 
            count[spend] += 1
            continue
        median = get_median(count, d)

        if spend >= 2 * median:
            ans += 1

        # 현재 spend를 count에 추가하고, d 이전의 spend를 count에서 제외시킴
        count[spend] += 1
        count[expenditure[idx-d]] -= 1

    return ans
Comments