[프로그래머스 / Swift] Lv.1 - 신고 결과 받기

박준혁 - Niro·2024년 9월 29일
1

프로그래머스

목록 보기
12/12
post-thumbnail

🔗 문제 링크


https://school.programmers.co.kr/learn/courses/30/lessons/92334

✅ 풀이


이번 문제는 각 유저별로 처리 결과 메일을 받은 횟수를 배열에 담아 return 하는 문제입니다!

여기서 제공한 문제의 조건을 보면 문제를 유추 할 수 있는 힌트가 숨겨져 있는거 같은데

한 유저를 여러 번 신고할 수도 있지만

라는 문장에서 Dictinary 로 풀어야겠다 라는 생각을 했고

동일한 유저에 대한 신고 횟수는 1회로 처리됩니다.

라는 의미는 Set 을 사용하면 되겠다 라는 생각을 했습니다!

유저별로 처리 결과 메일을 받은 횟수를 카운팅 해야하니 배열 하나가 더 필요하겠다고 생각도 했구요!

⌨️ 풀이 방법

func solution(_ id_list:[String], _ report:[String], _ k:Int) -> [Int] {
    var result = Array(repeating: 0, count: id_list.count)
    var reportData = [String: Set<String>]()
    
    for data in report {
        let splitData = data.split(separator: " ").map{ String($0) }
        reportData[splitData[1], default: Set()].insert(splitData[0])
    }
    
    for value in reportData.values {
        if value.count >= k {
            for person in value {
                result[id_list.firstIndex(of: person)!] += 1
            }
        }
    }
    
    return result
}

result 처리 결과 메일의 수를 담고 있는 배열이고 reportData 는 신고 당한 유저를 Key 로, 신고한 유저를 Value 로 만든 딕셔너리 입니다!

동일한 유저에 대해 신고 횟수는 1회로 처리를 해야하니까 Value 의 유형은 Set<String> 으로 미리 중복을 예방해주었습니다!

report 배열에 있는 데이터를 통해서 분류를 for 안에서 해주고 해당 유저가 신고한 유저의 신고 수가 k 이상일 경우를 찾아야 하고 똑같은 index 에 값을 넣어야 하기 때문에 이중 for 문을 사용해서 문제를 해결했습니다!

문제를 보고 쉽겠다 라고 생각했지만.. 딕셔너리 사용에서.. 에러가 발생했기도 하고 풀다 보니 헷깔리는 부분도 많았습니다..

⌨️ 다른 사람 풀이

func solution(_ id_list:[String], _ report:[String], _ k:Int) -> [Int] {
    var reported: [String: Int] = [:]
    var user: [String: [String]] = [:]

    for r in Set(report) {
        let splited = r.split(separator: " ").map { String($0) }
        user[splited[0]] = (user[splited[0]] ?? []) + [splited[1]]
        reported[splited[1]] = (reported[splited[1]] ?? 0) + 1
    }

    return id_list.map { id in
        return (user[id] ?? []).reduce(0) {
            $0 + ((reported[$1] ?? 0) >= k ? 1 : 0)
        }
    }
}

처음에 딱 보고.. 한참 동안 생각을 했습니다..
어떻게 하면 저렇게 바로 풀까 하구요..

reported 딕셔너리는 신고당한 사람을 key 로, 신고 수를 value 로 설정했고 user 딕셔너리는 신고한 사람을 key, 신고 당한 사람을 value 로 사용했습니다.

저는 딕셔너리의 value 유형을 Set<String> 으로 해서 중복을 예방하려고 했지만 이분은 report 매개변수 자체를 Set 으로 바꿔서 중복을 없애고 반복할 데이터의 수 자체를 줄여버렸습니다......

for r in Set(report) 이 코드는 정말 문제에서 신의 한 수 인거 같습니다....

그리고 저는 이중 for 문으로 id_list 를 처음부터 끝까지 반복하지만 위의 풀이는 딱 한번만 탐색하면서 각 사용자의 신고횟수도 한번만 조회하게 됩니다...

저의 풀이의 걸린시간만 봐도 테스트 3,9,14,20,21 에서 큰 차이가 났고 거의.. 10배 이상의 차이가 난 부분도 있었습니다

report 가 쵀대 200,000 개이니 당연하게 차이가 크게 벌어질 수 밖에 없는거 같네요

저의 코드가 더.. 직관적이고 이해하기 쉽겠지만...
고차함수를 이해하는데 좀 시간이 걸리겠지만...

훨씬 더 효율적인 코드인거는 틀림이 없네요...

한번에 코드를 적기에는 힘들겠지만 계속 코테 공부하면서 노력해야겠습니다!

profile
📱iOS Developer, 🍎 Apple Developer Academy @ POSTECH 1st, 💻 DO SOPT 33th iOS Part

0개의 댓글