[Swift 알고리즘] 2022 KAKAO BLIND RECRUITMENT 신고 결과 받기 문제 풀이

TIL 23일 차 - [Swift] 2022 KAKAO BLIND RECRUITMENT 신고 결과받기 알고리즘 문제 풀이

어제의 모닝 알고리즘 문제였는데 다음날 점심까지 붙잡고 있다가 드디어! 파란색으로 통과가 줄줄이 올라오는 거 보고 앉은자리에서 소리 지를 뻔했다..

 
 

문제 설명 요약

- 구할 것: 유저들이 신고한 이용자 중 정지당한 사람의 수 배열
- 한 사람이 동일한 유저를 여러 번 신고하더라도 신고 횟수는 1회로만 카운팅
- 입력값 k 이상 신고당한 유저는 이용 정지
 
 

1. 계산에 필요한 딕셔너리 선언하기

(1) 한 사람이 동일한 유저를 여러번 신고하더라도 신고 횟수는 1회로만 카운팅 되므로 Set을 이용해 중복 제거
(2) k번 이상 신고당한 사람만 정지되므로 정지신고 횟수를 저장할 딕셔너리 선언
(3) 유저별로 몇 개의 메일을 받을 것인지를 저장할 딕셔너리 선언
(4) 유저별로 몇 명을 선언했는지

func solution(_ id_list:[String], _ report:[String], _ k:Int) -> [Int] {
    
    // 한 사람이 같은 사람을 여러번 신고한 내역(중복)을 제거하기
    var reportSet = Set(report)
    
    // 이용자별 정지신고 당한 횟수를 저장할 빈 딕셔너리
    var reportedDict = [String: Int]()

    // 이용자별 신고한 유저중 정지당한 유저의 횟수를 저장할 빈 딕셔너리
    var mailCount = [String: Int]()
    
    // 이용자별로 신고한 유저를 저장할 빈 딕셔너리
    var reporting = [String: [String]]() // key: 신고자, value: 신고당한 유저 배열

 
 

2. 앞에서 선언한 딕셔너리에 값 대입하기

(1) reportSet의 각 원소를 공백을 기준으로 split 하여 0번째 인덱스는 reporter, 1번째 인덱스 값은 reported로 선언
(2) 선언된 reporter, reported를 적절히 대입

    // reportSet 돌면서 key, value에 각각 값 대입
    for report in reportSet {
        let reporter = report.split(separator: " ")[0] // 공백 기준 앞: 신고자
        let reported = report.split(separator: " ")[1] // 공백 기준 뒤: 신고당한 유저
        
        reportedDict[String(reported), default: 0] += 1 // 신고당한 횟수 카운팅
        reporting[String(reporter), default: []].append(String(reported))
    }

 
 

3.  k번 이상 신고당한 유저의 수 카운팅 하여 배열에 집어넣고 return 하기

(1) 신고당한 유저 중 k회 이상 신고 당한 유저의 수만 카운팅 하여 mailCount의 value에 대입
(2) return 할 Int형 배열 선언
(3) mailCount의 key값에 입력받은 id_list 배열 순으로 넣고 매칭된 value값을 꺼내 result 배열에 대입
(4) result 배열을 return

    // reporting의 key: 신고한 유저, value: 신고 당한 유저 배열
    for (key, value) in reporting {
    	// 신고당한 유저 배열 중 신고당한 횟수가 k회 이상인 유저의 수만 카운팅하여 mailCount의 value값에 대입
        mailCount[key] = value.filter { reportedDict[$0, default: 0] >= k }.count
    }
    
    // 정답을 return할 Int형 배열인 result 선언
    var result = [Int]()
    
    // 입력받은 유저 배열(id_list) 순으로 mailCount의 value값을 result에 append
    for i in id_list {
        result.append(mailCount[i, default: 0])
    }
    return result
}

 
 
 

최종 풀이 코드

func solution(_ id_list:[String], _ report:[String], _ k:Int) -> [Int] {
    
    // 한 사람이 같은 사람을 여러번 신고한 내역(중복)을 제거하기
    var reportSet = Set(report)
    
    // 이용자별 정지신고 당한 횟수를 저장할 빈 딕셔너리
    var reportedDict = [String: Int]()

    // 이용자별 신고한 유저중 정지당한 유저의 횟수를 저장할 빈 딕셔너리
    var mailCount = [String: Int]()
    
    // 이용자별로 신고한 유저를 저장할 빈 딕셔너리
    var reporting = [String: [String]]() // key: 신고자, value: 신고당한 유저 배열
    
    // reportSet 돌면서 key, value에 각각 값 대입
    for report in reportSet {
        let reporter = report.split(separator: " ")[0] // 공백 기준 앞: 신고자
        let reported = report.split(separator: " ")[1] // 공백 기준 뒤: 신고당한 유저
        
        reportedDict[String(reported), default: 0] += 1 // 신고당한 횟수 카운팅
        reporting[String(reporter), default: []].append(String(reported))
    }
    
    // reporting의 key: 신고한 유저, value: 신고 당한 유저 배열
    for (key, value) in reporting {
    	// 신고당한 유저 배열 중 신고당한 횟수가 k회 이상인 유저의 수만 카운팅하여 mailCount의 value값에 대입
        mailCount[key] = value.filter { reportedDict[$0, default: 0] >= k }.count
    }
    
    // 정답을 return할 Int형 배열인 result 선언
    var result = [Int]()
    
    // 입력받은 유저 배열(id_list) 순으로 mailCount의 value값을 result에 append
    for i in id_list {
        result.append(mailCount[i, default: 0])
    }
    return result
}