https://programmers.co.kr/learn/courses/30/lessons/72412
1. 전체 코드
from bisect import bisect_left, bisect_right
from itertools import combinations
from collections import defaultdict
import heapq
import re
def solution(info, query):
answer = []
member = []
q = []
d = defaultdict(list)
for j in info:
a = j.split()
member.append(a) ## a = ['java', 'backend', 'junior', 'pizza', '150']
for j in query:
s = re.sub('and', '', j)
s = s.split()
q.append(s) ## s = ['-', '-', '-', 'chicken', '100']
a = [0, 1, 2, 3]
for k in member:
temp = []
# '-' 없는 검색 -> 1개
temp.append(k[:4])
# '-' 1개 -> 4C1 -> 4개
temp.append(['-', k[1], k[2], k[3]])
temp.append([k[0], '-', k[2], k[3]])
temp.append([k[0], k[1], '-', k[3]])
temp.append([k[0], k[1], k[2], '-'])
# '-' 2개 -> 4C2 -> 6개
arr_two = list(map(list, combinations(a, 2)))
for j in arr_two:
temp_k = k[:4]
x, y = j
temp_k[x] = '-'
temp_k[y] = '-'
temp.append(temp_k[:])
# '-' 3개 -> 4C3 -> 4개
arr_three = list(map(list, combinations(a, 3)))
for j in arr_three:
temp_k = k[:4]
x, y, z = j
temp_k[x] = '-'
temp_k[y] = '-'
temp_k[z] = '-'
temp.append(temp_k[:])
# '-' 4개 -> 1개
temp.append(['-', '-', '-', '-'])
for j in temp:
d[''.join(j)].append(int(k[4]))
# 풀이-4번 설명
for key in d.keys():
d[key].sort()
# 효율성 X -> 풀이-3번 설명
# for j in q:
# d[''.join(j[:4])].sort()
for j in q:
a = d[''.join(j[:4])]
left = bisect_left(a, int(j[4]))
right = bisect_right(a, 100000)
answer.append(right - left)
return answer
2. 후기 및 설명
- 시간복잡도
O(N*M)
의 풀이로 풀게 된다면, O(50,000 * 100,000) = O(5,000,000,000)
의 시간복잡도가 소요된다. 체점용 서버는 파이썬이 1초에 약 20,000,000
번 정도의 연산만 처리할 수 있다고 가정하고 문제를 풀어야하기 때문에, 이 풀이의 경우 25
초의 시간이 소요된다. 이 문제의 정답률이 낮았던 이유는 효율성 테스트를 통과하기 매우 까다롭기 때문이다.
member
배열에 담긴 k = ['java', 'backend', 'junior', 'pizza', '150']
가 어떠한 query(=q)
들로 검색될 수 있을지 생각해야 한다. '-'
를 생각한다면 각각의 k
는 아래의 16가지 형식의 그룹으로 묶을 수 있다. 자세한 설명은 해설 참고

- 처음에는
q(=query)
에 해당하는 d[''.join(j[:4])]
의 값만 정렬 하는게 효율적이라 생각했지만, 효율성 테스트를 통과하지 못했다. 예제와 다르게도 q
는 최대 100,000
개의 값을 가질 수 있고 sort()
는 O(nlogn)
의 시간복잡도를 가지기 때문에 각 그룹에 묶인 점수들d[key] =[150, 200, 80 .....]
의 길이 n
이 클 경우 시간초과가 발생할 수 있다고 생각했다. 또한 동일한 d[key]
에 대해 중복된 sort()
가 수행되는 것도 생각할 수 있다.
- 사전형
d
의 길이는 모든query
조합을 고려한다 해도 기껏해야 수백, 수천가지의 그룹이 한계일 것이다. 따라서 for문을 통한 동일한 sort()
수행 시 시간복잡도 측면에서 훨씬 유리하다.