Problem Solving/Programmers

【프로그래머스】 신고 결과 받기 (Kotlin)

까망사과 2023. 2. 3. 15:00

문제

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

풀이

신고 기록 배열을 순회하며 두 가지 맵에 데이터를 추가한다.

  • targetListMap
    각 사용자가 신고한 다른 사용자 리스트를 포함하는 맵
  • reportCountMap
    각 사용자가 신고된 횟수를 포함하는 맵

각 사용자가 신고한 다른 사용자가 정지된 경우 배열의 해당하는 원소를 증가시킨다.

 

맵에 데이터 추가하기

report에서 중복을 제거하고 다음을 반복한다.

  1. 신고 기록 데이터를 신고자와 피신고자로 분리한다.
  2. targetListMap에서 신고자에 해당하는 리스트에 피신고자를 추가한다.
  3. reportCountMap에서 피신고자에 해당하는 값을 증가시킨다.
// 키: 사용자, 값: 신고한 다른 사용자 리스트
val targetListMap = hashMapOf<String, ArrayList<String>>()

// 키: 사용자, 값: 신고된 횟수
val reportCountMap = hashMapOf<String, Int>()

// 중복되는 신고 기록을 제거한다.
for (record in report.distinct()) {

    // 신고 기록을 신고자와 피신고자로 분리한다.
    val (reporter, target) = record.split(" ").let { it[0] to it[1] }
    
    // 신고한 사용자 리스트에 피신고자를 추가한다.
    targetListMap.getOrPut(reporter) { arrayListOf() }.add(target)
    
    // 피신고자의 신고된 횟수를 증가시킨다.
    reportCountMap[target] = reportCountMap.getOrDefault(target, 0) + 1
}

 

정지된 사용자 필터링하기

id_list의 크기에 맞춰 정답 배열을 준비하고 각 원소를 0으로 초기화한다.

각 사용자에 대해 신고한 사용자가 있는 경우 해당 피신고자의 신고 횟수가 k회 이상이면 정답 배열의 원소를 증가시킨다.

// 정답 배열의 각 원소를 0으로 초기화한다.
val answer = IntArray(id_list.size) { 0 }

for (i in id_list.indices) {

    // 신고한 사용자가 있다면 해당 피신고자에 대해 반복한다.
    targetListMap[id_list[i]]?.forEach {
    
        // 피신고자가 신고된 횟수가 k번 이상이면 정답 배열의 원소를 증가시킨다.
        // 신고되었다면 reportCountMap에 값이 저장되므로 !! 연산자를 사용한다.
        if (reportCountMap[it]!! >= k) {
            answer[i]++
        }
    }
}

 

코드

내 코드

 

GitHub - blacksg/ProblemSolving

Contribute to blacksg/ProblemSolving development by creating an account on GitHub.

github.com

class Solution {
    fun solution(id_list: Array<String>, report: Array<String>, k: Int): IntArray {
        val answer = IntArray(id_list.size) { 0 }
        val targetListMap = hashMapOf<String, ArrayList<String>>()
        val reportCountMap = hashMapOf<String, Int>()
        for (record in report.distinct()) {
            val (reporter, target) = record.split(" ").let { it[0] to it[1] }
            targetListMap.getOrPut(reporter) { arrayListOf() }.add(target)
            reportCountMap[target] = reportCountMap.getOrDefault(target, 0) + 1
        }
        for (i in id_list.indices) {
            targetListMap[id_list[i]]?.forEach {
                if (reportCountMap[it]!! >= k) {
                    answer[i]++
                }
            }
        }
        return answer
    }
}

 

다른 코드

등록된 풀이 중 좋아요 수가 가장 많은 것이다.

메서드 체인 하나로만 구성된 것을 읽기 편하도록 분리해보았다.

 

GitHub - blacksg/ProblemSolving

Contribute to blacksg/ProblemSolving development by creating an account on GitHub.

github.com

class Solution {
    fun solution(id_list: Array<String>, report: Array<String>, k: Int): IntArray {
    	
        // report에서 중복을 제거하고 각 원소를 분리
        val distinctReports = report.distinct().map { it.split(" ") }
        
        // 정지된 사용자가 신고된 기록 리스트
        val suspendedReports = distinctReports.groupBy { it[1] }
            .asSequence()
            .map { it.value }
            .filter { it.size >= k }
            .flatten()
            
        // 키: 신고자, 값: 신고하여 정지된 사용자 수
        val reportCounts = suspendedReports.map { it[0] }
            .groupingBy { it }
            .eachCount()
            
        return id_list.map { reportCounts.getOrDefault(it, 0) }.toIntArray()
    }
}