[프로그래머스] 후보키

해시, 순열과 조합


해당 문제는 Python으로 풀면 유독 쉽게 풀 수 있는 문제인듯 하다. combinations, issubset 모듈을 사용하여 해결할 수 있다.

해당 문제는 말 그대로 후보키에 대한 정의에 만족하는 집합의 개수를 찾으라는 문제이다. 따라서 집합 원소 개수가 낮은 부분집합부터 차례대로 찾아올라가며 테스트 하면 된다.

구현


여기서 2번째 예시의 결과가 5가 나와야 한다. {0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}

{2, 3}은 안된다. 크기가 더 큰 부분집합은 최소성에 위배되어 더이상 찾을 수 없다. 이 경우에 대해서 제대로 고민해 보면 문제를 이해하는데 많은 도움을 얻을 수 있을 것이다.

from itertools import combinations

def solution(relation):
    col, row = len(relation[0]), len(relation)

    index = set(i for i in range(col))
    max_candidate_key = []

    for c in range(1, col + 1):
        for comb in combinations(list(index), c):       # 개수 만큼 뽑는다.
            tmp = set()
            for rel in relation:
                row = tuple(rel[c] for c in comb)       # 해당 열의 인덱스에 해당하는 값을 튜플로 임시 생성한다.
                if row in tmp:                          # 해당 값이 "유일(uniqueness)"하지 않다면
                    break
                tmp.add(row)
            else:
                for key in max_candidate_key:           # 앞선 단계에서 등록된 후보키를 순회하며
                    if set(key).issubset(set(comb)):    # 해당 후보키가 최소성을 만족하는지 체크
                        break
                else:
                    max_candidate_key.append(comb)

    return len(max_candidate_key)

print(solution([["100","ryan","music","2"],
                ["200","apeach","math","2"],
                ["300","tube","computer","3"],
                ["400","con","computer","4"],
                ["500","muzi","music","3"],
                ["600","apeach","music","2"]]
               )) >> 2

print(solution([
    ["a", "b", "c", "d"],
    ["a", "c", "d", "e"],
    ["b", "b", "e", "f"],
    ["c", "d", "c", "d"]
])) >> 5