알고리즘 풀이/Search

Programmers 순위 검색

갓우태 2021. 8. 27. 23:19

링크 : https://programmers.co.kr/learn/courses/30/lessons/72412

 

코딩테스트 연습 - 순위 검색

["java backend junior pizza 150","python frontend senior chicken 210","python frontend senior chicken 150","cpp backend senior pizza 260","java backend junior chicken 80","python backend senior chicken 50"] ["java and backend and junior and pizza 100","pyt

programmers.co.kr

2021 KAKAO BLIND RECRUITMENT 순위 검색

 

이거 풀때 너무 힘들어서,,, 작성한다

 

첫번째로 접근한 방법은 input인 info List를 객체로 변환해 저장하고, 죄다 비교하는 거였다.

당연히 효율성에서 빵점이 나왔다.

Kakao Tech에서 나온 해설을 열심히 보며 코드를 작성했다.

 

예시

    info 1 : "java backend junior pizza 150"

    info 2 : "java frontend senior pizza 200"

 

1. info 정보 찢기

만약 info1로 "java backend junior pizza 150" 이 들어왔다고 하면,

질문으로 "- backend junior pizza" 가 들어오거나 "java - junior pizza"가 들어와도 모두 해당이 된다.

그래서 "java backend junior pizza"로 query가 통과될 수 있는 모든 경우의 수를 만든다. (그게 16가지)

 

  언어 분야 경력 음식 점수
1 java backend junior pizza 150
2 - backend junior pizza 150
3 java - junior pizza 150
4 java backend - pizza 150
5 java backend junior - 150
6 - - junior pizza 150
7 - backend - pizza 150
8 - backend junior - 150
9 java - - pizza 150
10 java - junior - 150
11 java backend - - 150
12 - - - pizza 150
13 - - junior - 150
14 - backend - - 150
15 java - - - 150
16 - - - - 150

이렇게 한명의 지원자 정보에 대해 16가지로 나타낼 수 있다.

다음 지원자 정보인 "java frontend senior pizza 200"을 info2라고 한다면,

info2 또한 위 표처럼 16가지로 쪼개질 수 있다. 그 중 info1과 겹치는 경우는

 

언어 분야 경력 음식 점수
java - - pizza [150, 200]
- - - pizza [150, 200]
java - - - [150, 200]
- - - - [150, 200]

이렇게 4가지가 될 것이다.

만약 query로 "java - - pizza 170"이 들어온다면, 위의 표에서 점수에서 170이 넘는 지원자는 한명 뿐이니, 답은 1이 된다.

 

이제 언어, 분야, 경력, 음식을 합쳐서 Map의 key값으로 만들고, 점수 List를 value로 설정한다.

이렇게 하면 반을 왔다.

 

이대로 모두 순차적으로 점수를 탐색하면 효율성에서 0점을 맞는다.

Kakao Tech에선 이진 탐색(binary search)을 사용하기를 권한다.

우선 map의 각 value들을 정렬한 뒤, binary search를 이용해 탐색하면 답을 구할 수 있는데

 

Kotlin에서 제공하는 binarySearch 함수는 동일한 요소가 있는 경우 제일 최소 인덱스 반환을 보장하지 않는다고 하여

직접 구현했다.

 

fun recursive(map: MutableMap<String, MutableList<Int>>, strs: List<String>, checked: Array<Boolean>, index : Int, depth: Int, max_depth: Int) {
    if(depth == max_depth) {
        // check된곳 "-"로 치환
        var str = StringBuilder()

        (0 until 4).forEach { j ->
            if (checked[j]) {
                str.append("-")
            } else {
                str.append(strs[j])
            }
        }

        val key = str.toString()
        val score = strs[4].toInt()
        if(map.containsKey(key)) {
            map[key]!!.add(score)
        }else {
            map[key] = mutableListOf(score)
        }
    }

    for(i in index until 4) {
        checked[i] = true
        recursive(map, strs, checked, i+1,depth+1, max_depth)
        checked[i] = false
    }
}

fun binarySearch(list: MutableList<Int>, target: Int):Int {
    var start = 0
    var end = list.size
    var mid: Int
    while (end - start > 0) {
        mid = (start + end) / 2
        if(target <= list[mid]) {
            end = mid
        }
        else {
            start = mid + 1
        }
    }

    return end
}

class Solution {
    fun solution(info: Array<String>, query: Array<String>): IntArray {
        var answerList = mutableListOf<Int>()
        var info_map = mutableMapOf<String, MutableList<Int>>()

        for (i in info) {
            val splitInfo = i.split(" ")

            for(j in 0..4){
                recursive(info_map, splitInfo, Array(4) {false}, 0,0, j)
            }
        }

        for(k in info_map.keys) {
            info_map[k]!!.sort()
        }

        for(q in query) {
            val str = q.replace("and ", "").split(" ")
            val key = str[0] + str[1] + str[2] + str[3]

            when(val scoreList = info_map[key]) {
                null -> answerList.add(0)
                else -> answerList.add(scoreList.size - binarySearch(scoreList, str[4].toInt()))
            }
        }
        return answerList.toIntArray()
    }
}

 

반응형