오늘 내가 풀어본 문제는 2022년 카카오 코딩테스트 문제였던 '신고 결과 받기' 문제이다.
https://school.programmers.co.kr/learn/courses/30/lessons/92334
코딩테스트 연습 - 신고 결과 받기
신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다. 각 유저는 한 번에 한 명의 유저를 신고할 수 있습니다. 신고 횟수에 제한은 없습니다. 서로 다른 유저를 계속해서 신고할 수 있습니다. 한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 1회로 처리됩니다. k번 이상 신고된 유저는 게시판 이용이 정지되며, 해당 유저를 신고한 모든 유저에게 정지 사실을 메일로 발송합니다. 유저가 신고한 모든 내용을 취합하여 마지막에 ...
school.programmers.co.kr
문제를 보고, id_list와 report가 String형태로 저장되어있다는것을 보고 어제 공부한 map을 사용하면 쉽고 편하게 관리할 수 있겠다고 생각해서 map을 이용해보았다.
val answerMap = mutableMapOf<String, Int>()
val reportedMap = mutableMapOf<String, MutableSet<String>>()
val reportSet = mutableSetOf<Pair<String, String>>()
각 사용자별로 신고 횟수를 저장할 answerMap,
신고당한 사용자가 누구누구에게 신고당했는지 저장하는 reportedMap,
신고한 사용자와 신고당한 사용자의 쌍을 저장할 reportSet
세가지를 먼저 선언해주었다. 그후,
id_list.forEach {
reportedMap[it] = mutableSetOf()
answerMap[it] = 0
}
주어진 id_list배열의 각 값들을 가져와서, 아직은 신고를 하는 코드를 작성하지 않았으니 모두가 신고를 0번 당했다고 생각해서, reportedMap에 key값에는 사용자들의 이름을 중복을 허용하지않게 set형식으로 넣어주었고,
answerMap에서도 역시 key값에 사용자들의 이름을 넣고 그 값을 0으로 넣어줬다.
report.forEach {
val splited = it.split(" ")
val reportUser = splited.first()
val reportedUser = splited.last()
reportedMap[reportedUser]!!.add(it)
reportSet.add(Pair(reportUser, reportedUser))
}
다음으로, 누가 누구를 신고했는지 알려주는 report배열을 가져와서, " "를 기준으로 앞에있는값은 신고자, 뒤에있는 값은 신고당한자로 각각 reportUser, reportedUser로 선언해주었다.
그후, 누가 누구에게 신고를 당했는지 선언해뒀덴 map에 넣어준다.
key값에는 신고당한사람인 reportedUser를넣어서 값을 가져와주는데, (기존에 이 키에대한 값이 없으면 null일것이기 때문이 !!를 사용해준다.) 만약 report배열에서 가져온 값이 ["muzi frodo"]라면, frodo라는 키를 가진애를 가져와서, 'muzi frodo'라는 문자열을 추가해준다.
-> 이렇게 되면 reportedMap에는 id_list에 있는 사용자들의 값이 key값으로 들어있고, 그 key값을 불러오면 누가 자신을 신고했는지에 대한 값이 들어있게 되는 것이다.
그리고, reportSet에 신고자와 신고당한자 쌍의 값을 넣어준다.
reportSet.forEach {
if (reportedMap[it.second]!!.size >= k) {
answerMap[it.first] = answerMap[it.first]!! +1
}
}
신고자와 신고당한자의 쌍이 저장된 reportSet을 가져와서 reportedMap의 두번째 값인 신고횟수의 size를 구해서, 문제에서 말한 k번이상 신고를 당했다면 각 사용자별로 신고횟수가 저장되어있는 answerMap에서 it.first, 즉 예를 들었었던 muzi frodo에서 muzi가 신고자이니, 신고자를 가져와서 1을 더해준다. -> 문제에서 원하는 사용자가 신고한사람이 정지를 당했을 경우, 1을 추가하는 로직이다.
val answerList = mutableListOf<Int>()
id_list.forEach {
answerList.add(answerMap[it]!!)
}
answer = answerList.toIntArray()
그후엔 리스트를 하나 만들어서, 각 사용자(key)에 대한 신고자횟수(value)를 저장해주고, 배열 형식으로 바꿔주며 return해주면 끝이 난다.
전체코드
class Solution {
fun solution(id_list: Array<String>, report: Array<String>, k: Int): IntArray {
var answer: IntArray
val answerMap = mutableMapOf<String, Int>()
val reportedMap = mutableMapOf<String, MutableSet<String>>() //신고당한 수
val reportSet = mutableSetOf<Pair<String, String>>()
id_list.forEach {
reportedMap[it] = mutableSetOf()
answerMap[it] = 0
}
report.forEach {
val splited = it.split(" ")
val reportUser = splited.first()
val reportedUser = splited.last()
reportedMap[reportedUser]!!.add(it)
reportSet.add(Pair(reportUser, reportedUser))
}
reportSet.forEach {
//reportSet에서 두번째에 있는 값이 신고당한사람이고,그사람이 k번이상 신고당했다면
if (reportedMap[it.second]!!.size >= k) {
answerMap[it.first] = answerMap[it.first]!! +1
}
}
val answerList = mutableListOf<Int>()
id_list.forEach {
answerList.add(answerMap[it]!!)
}
answer = answerList.toIntArray()
return answer
}
}
이 문제를 풀며, 지금까지 무식하게 알고리즘을 풀었던 나와 다르게, map을 사용해야겠다는 생각을 했고, 아직은 익숙하지 않아서 오랜 시간이 걸렸지만 문제에서 원하는 방식으로 풀었다고 생각하면 기분이 좋아졌다,,!
중요한 사실또한 깨달았다. 문제를 읽고, 무작정 풀지 말고 어떤값이 필요한지 생각해보고 어떤 map을 만들어서 어떤 값을 저장해야할지 먼저 생각해보고 문제를 푼다면 더 좋을것 같다는 생각이 들었다.