알고리즘

[프로그래머스 Lv1 - 2022 KAKAO BLIND RECRUITMENT] 신고 결과 받기 (Python)

lwkejpf 2022. 6. 28. 23:37


def solution(id_list, report, k):
    li = dict()
    result = dict()
    
    send_li = []
    receive_li = []
    answer = []
    all = []
    
    for i in range(len(report)) :
        send, receive = report[i].split()
        if [send, receive] in all :
            continue
        else :
            send_li.append(send)
            receive_li.append(receive)
            all.append([send, receive])
            li[receive] = 0

    for i in id_list :
        result[i] = 0
        
    for j in receive_li :
        li[j] += 1
        
    for key, value in li.items() :
        if value >= k :
            idx = [i for i, x in enumerate(receive_li) if x == key]
            for i in idx :
                result[send_li[i]] += 1

    for value in result.values() :
        answer.append(value)
        
    return answer

 

처음에 아무 생각없이 구현에만 신경썼다가

 

 

시간 초과 대참사 발생 ,,, 

 

 

 

 

 

'한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 1회로 처리됩니다.'

 

이 조건을 set() 함수로 바로 처리할 수 있었다는거... ㄹ 왜 몰랐지 ㅠ

 

 

def solution(id_list, reports, k):
    reports = set(reports)
    li = dict()    
    answer = dict()  
    send_li = []
    receive_li = []
    
    for id in id_list :
        li[id] = 0
        answer[id] = 0
        
    for report in reports :
        send, receive = report.split()
        send_li.append(send)
        receive_li.append(receive)
        li[receive] += 1
        
        if li[receive] >= k :
            idx = [i for i, x in enumerate(receive_li) if x == receive]
            for id in idx :
                answer[send_li[id]] += 1
                
    answer = list(answer.values())
    return answer

 

그나마 코드는 간결해졌지만

 

 이번엔 테스트케이스 죄다 오류남 ..ㅠ

 

 

그리고 쫌 더 헤매다가 오류난 이유를 알아차림.. 드디어?

 

def solution(id_list, reports, k):
    reports = set(reports)
    li = dict()    
    answer = dict()  
    
    send_li = []
    receive_li = []
    
    for id in id_list :
        li[id] = 0
        answer[id] = 0
        
    for report in reports :
        send, receive = report.split()
        send_li.append(send)
        receive_li.append(receive)
        li[receive] += 1
        
        if li[receive] == k :
            idx = [i for i, x in enumerate(receive_li) if x == receive]
            for id in idx :
                answer[send_li[id]] += 1
                
        elif li[receive] > k :
            answer[send] += 1
            
    answer = list(answer.values())
    
    return answer

 

 

혼자 해냈다 ... !!!!!!!!

 


 

놓치고 있었던 게 신고 횟수가 k 번일 때랑 k 보다 많아졌을 때를 구분해서 적어줘야 됐었다 ,,,


만약 A 가 신고당한 횟수가 딱 k 번 됐을 때라면

지금까지 A 를 신고했던 모든 유저들의 메일 횟수가 +1 해주면 됨. 


근데 만약 A 가 이후에 한 번 더 신고당해서 k 번을 넘어버리게 되면

그냥 현재 신고한 유저의 메일 횟수만 +1 해주면 된다.

 

어차피 처음에 set() 으로 중복을 없앴기 때문에

현재 A 를 신고한 유저는 처음 들어오게 .. 된다고 설명해야 되나 예시로 설명하는 게 빠를 듯

 


3번째 테스트케이스를 예시로 설명해봄 

 

 

reports 배열에서 중복으로 들어온 "c d" 는 애초에 set() 으로 제거해줬기 때문에

실질적으로 reports 배열은 ["a b", "c d", "a d"] 가 됨. (set 은 순서가 없지만 일단..!!)

 

 

 

그리고 id_ist 에 들어온 요소를 하나씩 순회해서

초기값을 0으로 둔 딕셔너리를 2개 생성

 

- 딕셔너리 li : 각 유저들의 신고당한 횟수

- 딕셔너리 answer : 각 유저들의 메일받는 횟수

 

 

 

그리고 reports 배열 요소를 하나씩 순회하면서 공백을 기준으로 split 해서

앞에 있는 단어, 즉 신고한 유저는 send_li 에 추가

뒤에 있는 단어, 즉 신고당한 유저는 receive_li 에 추가

 

그리고 현재 receive 의 신고당한 횟수를 +1 해줌.

 

 

 

신고 횟수 +1 했는데 현재 receive 의 신고당한 횟수가 k 번이 되었다면

receive_li 에서 receive 의 인덱스를 모두 idx 에 저장

 

(만약 enumerate 안 쓰고 그냥 for문으로 돌리게 되면

맨 처음 나타난 인덱스 하나만 저장되기 때문에 enumerate 사용한거!!)

 

idx 에 저장된 인덱스를 하나씩 돌면서

현재 receive 를 신고했던 모든 유저들의 메일 받는 횟수를 +1 해줌.

 

 

근데 만약 신고 횟수 +1 했는데 현재 receive 의 신고당한 횟수가 k 번을 넘어섰다면 ???

 

 k번일 때 receive 신고했던 유저들은 이미 위에서 +1 해줬기 때문에

현재 send 메일 받는 횟수만 +1 해주면 됨.

 

참고로 메일 받는 횟수는 신고 k번 이상 당한 유저들의 아이디 개수라는거!!

k 번 넘을 때마다 계속 메일 횟수 +1 해주는 게 아니라는거..!!!