[카카오] 2021 블라인드 공채 - 순위 검색

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

작년 9월에 신입공채 1차 코딩테스트가 있었습니다. 그 중 효율성을 통과하지 못했던 문제인데, 프로그래머스에 문제가 올라와 풀이합니다.

가장 큰 문제는 Graph 구조로 이 문제에 접근했다는 점입니다. Trie를 이용해 모든 경우의 수를 이어서 탐색하는 방식으로 접근했는데, 정확성은 통과했지만 효율성을 통과하지 못했습니다.

이 문제는 한 번에 원하는 조건의 지원자 수에 접근할 수 있도록 풀어야 시간 초과가 나지 않습니다.

https://tech.kakao.com/2021/01/25/2021-kakao-recruitment-round-1/

해설은 이 곳에 나와있습니다.

코드

get_subset

1
2
3
4
5
6
7
8
9
10
11
12
13
def get_subset(arr): # info에서 -를 포함해 가능한 모든 경우의 수를 부분집합으로 구함.
    n = len(arr)
    result = []
    for i in range(1 << n):
        temp = []
        for j in range(n):
            if i & (1 << j):
                temp.append(j)
        temp_arr = arr[:]
        for idx in temp:
            temp_arr[idx] = '-'
        result.append(' '.join(temp_arr))
    return result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def get_answer_by_binary_search(score, arr):
    if not arr: return 0
    start, end = 0, len(arr)
    mid = (start + end) // 2

    while start < end: # 기준 점수 이상이 처음 나오는 위치를 찾음.
        mid = (start + end) // 2
        value = arr[mid]
        if value >= score:
            end = mid
        else:
            start = mid+1

    return len(arr) - end

solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def solution(info, query):
    answer = []
    answer_dict = {}
    for i in info:
        i = i.split(' ')
        for res in get_subset(i[:-1]):
            answer_dict[res] = answer_dict.get(res, [])
            answer_dict[res].append(int(i[-1]))

    for value in answer_dict.values():
        value.sort()

    for q in query:
        q_list = q.split(' ')
        score = int(q_list.pop())
        q_list = [word for idx, word in enumerate(q_list) if idx%2 == 0]
        condition = ' '.join(q_list)
        answer.append(get_answer_by_binary_search(score, answer_dict.get(condition)))

    return answer

solution에서 하는 일은 간단합니다.

"java backend junior pizza 150" 형태로 들어오는 info에서 “java backend junior pizza”만을 분리한 뒤, 이 info가 속할 수 있는 모든 경우의 수를 구합니다. get_subset 함수가 이 역할을 하게 됩니다.

언어 직군 경력 소울 푸드 점수
java backend junior pizza 150
– backend junior pizza 150
java – junior pizza 150
java backend – pizza 150
java backend junior – 150
– – junior pizza 150
– backend – pizza 150
… (생략)        
java – – – 150
– – – – 150
1
2
3
4
5
# get_subset을 통해 얻게 되는 list는 다음과 같습니다.

# ["java backend junoir pizza", "- backend junoir pizza", "java - junior pizza", "java backend - pizza", "- - junior pizza", ......]

# 위 list의 원소가 딕셔너리의 key가 되고, value인 list에 점수를 append합니다.

lower bound(binary search)를 이용해 답을 구하기 때문에 모든 value를 정렬해주고, 답을 구합니다. get_answer_by_binary_search 함수가 이 역할을 하게 됩니다.


검색 조건을 어떻게 그룹화하느냐에 따라 효율성 체크 여부가 갈렸던 문제입니다. 보자마자 Trie가 생각나서 다른 방법은 미처 생각하지 못했는데 조금 더 유연한 사고로 코딩테스트에 임해야겠습니다.