후보키가 될 수 있는 어트리뷰트(칼럼)의 경우의 수를 미리 구한다. 각 경우의 수에 따라 튜플을 확인하며 중복된 튜플이 있을 경우 프라이머리 키 조건을 위배하므로 False, 중복되지 않았을 경우에 후보키가 될 수 있다. 이때 이 후보키의 부분 집합이 이미 후보키인 경우는 제외해야 한다(훨씬 더 적은 경우의 수로 조합했을 때에도 후보키로 적용할 수 있기 때문이다).
from itertools import combinations
def solution(relation):
col_num = len(relation[0])
key_range = list(range(col_num))
candidate_keys = []
combs = []
for i in range(1, col_num+1):
combs += combinations(key_range, i)
for comb in combs:
checks = []
check = True
for record in relation:
rec = [record[i] for i in comb]
if rec not in checks: checks.append(rec)
else:
check= False
break
if check:
minimal = True
for candidate_key in candidate_keys:
if set(comb).issuperset(candidate_key):
minimal = False
break
if minimal: candidate_keys.append(comb)
return len(candidate_keys)
테스트 1 〉 통과 (0.03ms, 10.3MB)
테스트 2 〉 통과 (0.03ms, 10.4MB)
테스트 3 〉 통과 (0.05ms, 10.2MB)
테스트 4 〉 통과 (0.05ms, 10.2MB)
테스트 5 〉 통과 (0.04ms, 10.3MB)
테스트 6 〉 통과 (0.01ms, 10.2MB)
테스트 7 〉 통과 (0.01ms, 10.3MB)
테스트 8 〉 통과 (0.01ms, 10.3MB)
테스트 9 〉 통과 (0.08ms, 10.2MB)
테스트 10 〉 통과 (0.14ms, 10.3MB)
테스트 11 〉 통과 (0.24ms, 10.3MB)
테스트 12 〉 통과 (0.64ms, 10.3MB)
테스트 13 〉 통과 (0.22ms, 10.2MB)
테스트 14 〉 통과 (0.05ms, 10.3MB)
테스트 15 〉 통과 (0.03ms, 10.2MB)
테스트 16 〉 통과 (0.04ms, 10.3MB)
테스트 17 〉 통과 (0.07ms, 10.2MB)
테스트 18 〉 통과 (2.96ms, 10.3MB)
테스트 19 〉 통과 (1.21ms, 10.3MB)
테스트 20 〉 통과 (2.76ms, 10.3MB)
테스트 21 〉 통과 (1.02ms, 10.4MB)
테스트 22 〉 통과 (0.54ms, 10.3MB)
테스트 23 〉 통과 (0.06ms, 10.3MB)
테스트 24 〉 통과 (1.80ms, 10.3MB)
테스트 25 〉 통과 (2.78ms, 10.3MB)
테스트 26 〉 통과 (1.43ms, 10.3MB)
테스트 27 〉 통과 (0.27ms, 10.3MB)
테스트 28 〉 통과 (0.30ms, 10.3MB)
from itertools import combinations
def solution(relation):
col_num = len(relation[0])
key_range = list(range(col_num))
candidate_keys = []
combs = []
for i in range(1, col_num+1):
combs += combinations(key_range, i)
while combs:
for comb in combs:
checks = []
check = True
for record in relation:
rec = [record[i] for i in comb]
if rec not in checks: checks.append(rec)
else:
check= False
break
if check:
cur_comb = comb
candidate_keys.append(cur_comb)
new_combs = []
for comb in combs:
if not set(cur_comb).issubset(set(comb)):
new_combs.append(comb)
combs = new_combs
break
else:
combs.remove(comb)
break
return len(candidate_keys)
테스트 1 〉 통과 (0.04ms, 10.3MB)
테스트 2 〉 통과 (0.03ms, 10.3MB)
테스트 3 〉 통과 (0.03ms, 10.3MB)
테스트 4 〉 통과 (0.04ms, 10.2MB)
테스트 5 〉 통과 (0.05ms, 10.3MB)
테스트 6 〉 통과 (0.01ms, 10.3MB)
테스트 7 〉 통과 (0.01ms, 10.3MB)
테스트 8 〉 통과 (0.02ms, 10.3MB)
테스트 9 〉 통과 (0.11ms, 10.3MB)
테스트 10 〉 통과 (0.04ms, 10.3MB)
테스트 11 〉 통과 (0.08ms, 10.4MB)
테스트 12 〉 통과 (0.24ms, 10.3MB)
테스트 13 〉 통과 (0.16ms, 10.4MB)
테스트 14 〉 통과 (0.04ms, 10.3MB)
테스트 15 〉 통과 (0.03ms, 10.3MB)
테스트 16 〉 통과 (0.05ms, 10.3MB)
테스트 17 〉 통과 (0.04ms, 10.2MB)
테스트 18 〉 통과 (0.63ms, 10.3MB)
테스트 19 〉 통과 (0.62ms, 10.2MB)
테스트 20 〉 통과 (1.51ms, 10.2MB)
테스트 21 〉 통과 (1.07ms, 10.2MB)
테스트 22 〉 통과 (1.27ms, 10.4MB)
테스트 23 〉 통과 (0.04ms, 10.3MB)
테스트 24 〉 통과 (0.71ms, 10.4MB)
테스트 25 〉 통과 (1.34ms, 10.3MB)
테스트 26 〉 통과 (0.65ms, 10.3MB)
테스트 27 〉 통과 (0.09ms, 10.2MB)
테스트 28 〉 통과 (0.15ms, 10.3MB)