1. 문제
- 주어진 relation 배열에서 후보키를 구하는 문제
- 유일성과 최소성을 만족해야함
- 후보키의 개수를 리턴
2. 풀이
- 풀이 방법 자체는 어렵지 않게 떠올릴 수 있으나 좀 깔끔하게 짤 수 없을까 하다가 오래걸림
- 각 키들의 모든 조합을 구한 후 중복이 배열에 중복이 없는지 체크(유일성)
- 단 최소성을 만족시키기 위해 a 가 후보키인 경우 [a, c] 조합을 계산할 필요 없음
- return_cases 함수로 모든 조합을 구한 후(인덱스를 구했으나 그냥 문자열로 구하는게 편했을듯, 유효성 체크할때), 모든 케이스에 대해 check_dup로 중복이 있는지(유일성) 체크, 그 뒤에 val_check로 최소성 체크, 최소성 만족한다면 check에 후보키로 등록, 마지막에 후보키의 개수를 리턴해줌
- 키가 [a, b, c, d]라 했을 때 처음에 check = [0, 0, 0, 0]으로 하고 후보키에 등록하면 1로 바꿔주는 식으로 짰었는데 이럴 경우 [b, c] , [b, d]가 후보키로 체크가 안 됨(b, c 가 후보키로 등록되는 순간 b가 1로 체크되기 때문에) -> 문자열로 조합을 짜야 최소성 검사하기가 쉬웠을까? 좀 더 효율적으로 짜려고 인덱스로 조합을 만든건데 결국 더 비효율적으로 짜버림
3. 코드
def solution(relation):
col = len(relation[0])
row = len(relation)
cases = []
for i in range(1, col+1) :
return_cases(0, i, cases, [], col)
check = []
while cases :
case = cases.pop(0)
if check_dup(check, case) :
continue
if val_check(relation, case) :
check.append(case)
return len(check)
def return_cases(idx, n, cases, path, col) :
if len(path) == n :
cases.append(path)
for i in range(idx, col) :
return_cases(i+1, n, cases, path + [i], col)
def val_check(arr, case) :
key = set()
for i in range(len(arr)) :
temp = tuple(arr[i][x] for x in case)
if temp in key :
return False
else :
key.add(temp)
return True
def check_dup(check, arr) :
for cand in check :
for i in range(len(cand)) :
if cand[i] not in arr :
break
if i == len(cand) - 1 :
return True
return False
4. 개선
- 조합이 파이썬 라이브러리에 있었음...
from itertools import combinations
arr = [1, 2, 3, 4, 5]
combi = list(combinations(arr, n)
-> 이런식으로 사용 가능함
- 비트마스크를 이용한 풀이도 가능함
해당 포스팅 참조 : itzjamie96.github.io/2020/10/15/python-bitwise-powersets/
'알고리즘 > 프로그래머스' 카테고리의 다른 글
2019 KAKAO BLIND RECRUITMENT- 길 찾기 게임, 파이썬 (0) | 2021.02.26 |
---|---|
2019 KAKAO BLIND RECRUITMENT- 무지의 먹방 라이브, 파이썬 (0) | 2021.02.25 |
2019 카카오 코딩테스트 기출 - 실패율 , 파이썬 (0) | 2021.02.24 |
2019 KAKAO BLIND RECRUITMENT - 오픈채팅방, 파이썬 (0) | 2021.02.23 |
2020 KAKAO BLIND RECRUITMENT - 가사 검색 (파이썬) (0) | 2021.02.19 |