[HackerRank] Fraudulent Activity Notifications

2 minute read

문제정보

어떻게 풀까?

주어진 날짜배열에서 현재날짜의 거래금액이 d만큼 이전날짜들 금액의 중간값 2배 이상이 되는 경우가 몇 번이나 있는지 구하는 문제이다.

역시나 그냥 구하면 Timed out이 뜬다. 중간값을 구하는 것을 효율화해야한다. 문제의 제약사항에서 expenditure[i]의 값이 0~200 사이라는 것이 포인트이다.

200개 크기의 배열을 만들고 대상 날짜들의 갯수만큼 count 를 올려놓고 이 값을 이용하는 것이다. 또한 날짜를 이동할 때마다 Queue와 같이 이전값은 빼고 새로운 값은 추가한다.

실수를 많이 한 문제이다…

문제풀이(Java)

import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.*;

public class Solution {
    
    static double findMedian(int[] cntArr, int d){
        int cnt = 0;
        double rslt = 0;

        if(d%2 != 0){
            for(int i=0; i<cntArr.length; i++){
                cnt += cntArr[i];

                if(cnt > d/2){
                    rslt = i;
                    break;
                }
            }
        }else{
            int first = 0;
            int second = 0;

            for(int i=0; i<cntArr.length; i++){
                cnt += cntArr[i];
                if(first == 0 && cnt >= d/2){
                    first = i;
                }
                if(second == 0 && cnt >= d/2 + 1){
                    second = i;
                    break;
                }
            }
            rslt = (first + second) / 2.0;
        }
        return rslt;
    }
    
    static int activityNotifications(int[] expenditure, int d) {
        int noti = 0;
        int[] cntArr = new int[201];

        for(int i=0; i<d; i++){
            cntArr[expenditure[i]]++;
        }

        for(int i=d; i<expenditure.length; i++){
            double median = findMedian(cntArr, d);

            if(2*median <=expenditure[i]){
                noti++;
            }

            cntArr[expenditure[i-d]]--;
            cntArr[expenditure[i]]++;
        }

        return noti;
    }

    private static final Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) throws IOException {
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(System.getenv("OUTPUT_PATH")));

        String[] nd = scanner.nextLine().split(" ");

        int n = Integer.parseInt(nd[0]);

        int d = Integer.parseInt(nd[1]);

        int[] expenditure = new int[n];

        String[] expenditureItems = scanner.nextLine().split(" ");
        scanner.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");

        for (int i = 0; i < n; i++) {
            int expenditureItem = Integer.parseInt(expenditureItems[i]);
            expenditure[i] = expenditureItem;
        }

        int result = activityNotifications(expenditure, d);

        bufferedWriter.write(String.valueOf(result));
        bufferedWriter.newLine();

        bufferedWriter.close();

        scanner.close();
    }
}

문제풀이(Python)

#!/bin/python3

import math
import os
import random
import re
import sys

def findMedian(cntarr, d):
    cnt = 0
    rslt = 0

    if d%2 is not 0:
        for i in range(len(cntarr)):
            cnt += cntarr[i]

            if cnt > d//2:
                rslt = i
                break
    else:
        first = 0
        second = 0

        for i, _ in enumerate(cntarr):
            cnt += cntarr[i]
            if first == 0 and cnt >= d//2:
                first = i
            if second == 0 and cnt >= d//2 + 1:
                second = i
                break
        rslt = (first+second) / 2
    return rslt


def activityNotifications(expenditure, d):
    noti = 0
    cntarr = [0 for _ in range(201)]
    for i in range(d):
        cntarr[expenditure[i]] += 1

    for i in range(d, len(expenditure)):
        median = findMedian(cntarr, d)

        if 2*median <= expenditure[i]:
            noti += 1

        cntarr[expenditure[i-d]] -= 1
        cntarr[expenditure[i]] += 1

    return noti


if __name__ == '__main__':
    fptr = open(os.environ['OUTPUT_PATH'], 'w')

    nd = input().split()

    n = int(nd[0])

    d = int(nd[1])

    expenditure = list(map(int, input().rstrip().split()))

    result = activityNotifications(expenditure, d)

    fptr.write(str(result) + '\n')

    fptr.close()

Leave a comment