문제설명은 너무 길어서 링크 참조바람
https://programmers.co.kr/learn/courses/30/lessons/72412
def solution(_info, _query):
answer = []
infoList = list(map(lambda x: x.split(' '), _info))
queryList = list(map(lambda x: x.replace('and ', ''), _query))
queryList = list(map(lambda x: x.split(' '), queryList))
queryset = list([set([]) for _ in range(5)] for _ in range(len(queryList)))
for i, query in enumerate(queryList):
for j in range(len(query)):
for info in infoList:
if query[j].isdigit():
if int(query[j]) <= int(info[j]) or query[j] == '-':
queryset[i][j].add(' '.join(info))
else:
if query[j] == info[j] or query[j] == '-':
queryset[i][j].add(' '.join(info))
for q in queryset:
winning = q[0] & q[1] & q[2] & q[3] & q[4]
cnt = 0
for w in winning:
cnt += _info.count(w)
answer.append(cnt)
return answer
정확성 테스트는 다 맞는데 효율성이 전부 시간초과나서 다른 사람의 풀이를 찾아보았다.
from itertools import combinations
def solution(info, query):
answer = []
db = {}
# 모든 경우의 수 만들기
for i in info:
temp = i.split(' ')
condition = temp[:-1]
score = int(temp[-1])
for n in range(5):
combi = list(combinations(range(4), n)) # (0,1,2,3) 중에서 n개 뽑기
for c in combi:
temp_con = condition[:]
for switch in c:
temp_con[switch] = '-'
key = ''.join(temp_con)
# 같은 것들 그룹화 해서 딕셔너리에 넣어 주기
if key in db:
db[key].append(score) # 문자열이 있으면 그 그룹에 점수 추가하고
else:
db[key] = [score] # 문자열이 없으면 그룹을 만들고 점수 추가
# 딕셔너리 모든 값들 그룹별로 정렬
for value in db.values():
value.sort()
for q in query:
# 쿼리 파싱
temp_q = q.replace('and ', '').split(' ')
q_condition = ''.join(temp_q[:-1])
q_score = int(temp_q[-1])
# 쿼리가 딕셔너리에 존재하면
if q_condition in db:
data = db[q_condition]
if len(data) > 0:
start, end = 0, len(data) # lower bound 알고리즘 통해 인덱스 찾고,
while start != end and start != len(data):
if data[(start + end) // 2] >= q_score:
end = (start + end) // 2
else:
start = (start + end) // 2 + 1
answer.append(len(data) - start) # 해당 인덱스부터 끝까지의 갯수가 정답
else:
answer.append(0)
return answer
먼저 info를 파싱하여 조건과 점수로 분리 한다
콤비네이션을 사용해 해당 조건으로 만들수 있는 모든 경우의수를
딕셔너리의 키로 두고 점수를 값으로 넣는다(그룹화 시켜서)
예를 들어 java backend junior pizza 150 이면
java/backend/junior/pizza
-/backend/junior/pizza
java/-/junior/pizza
{...}
-/-/-/pizza
-/-/-/-
이런식으로 16개의 조합을 만들어서 키로 두고
벨류를 점수로 넣는다 이때 그룹화 시켜야하므로 리스트로 집어넣는다
그 다음 딕셔너리 키값별로 벨류들을 전부 정렬해주고(이진 탐색을 위해)
쿼리가 딕셔너리에 존재하면
그 데이터들을 받아
이진탐색 알고리즘 중 하나인 lower bound 알고리즘으로 본인보다 크거나 같은 수 중
가장 작은 값의 인덱스를 찾아내서
그 인덱스부터 개수를 answer에 넣어 주면 된다.
핵심은 이진탐색을 사용하는 것인데
값을 찾는것이 아닌 해당 값보다 크거나 같은 값중 가장작은 값을 찾아야하므로
lower bound 알고리즘을 사용해서 효율성을 높이는 것이다.
정확성 맞추기는 쉬운 문제 같은데 효율성 맞추기가 너무 어려운것 같다
이게 lv.2 라니;;