자세한 설명과 제한사항은 프로그래머스에서 확인바랍니다.
가능한 모든 속성들의 조합을 만들고, 최소성과 유일성을 만족하는 조합만 추려내야한다.
DFS, BFS, bit 등을 이용한 방법을 통해 유일성을 만족하는 부분집합을 만들고 각 조합들의 최소성과 검사하면 풀어나갈 수 있다.
예를 들면 속성(1 ,3)과 속성 (1, 2, 3) 후보키 집합이 존재한다면 후자는 최소성을 만족하지 못한다.
프로그래머스 사이트가 아닌, visual studio 에서 코드를 작성해서 그대로 가져온 것 입니다. 일부 테스트 코드가 존재합니다.
추가설명 : ansVec은 flag 용도로 쓰입니다. 0번 인덱스에 몇개의 속성을 가지고 있는지를 저장하고 각 1번 ~ 15번 인덱스에는 조합에서 사용하는 속성에 1의 값을 넣어 다른 조합들과 비교합니다. ansVec은 속성 수를 기준으로 한번 정렬을 했기 때문에 순서대로 비교하면 최소성을 만족하는 조합들만 카운트 할 수 있습니다.
#include <string>
#include <vector>
#include <algorithm>
//https://programmers.co.kr/learn/courses/30/lessons/42890
using namespace std;
void DFS(vector<vector<string>>& relation, vector<int> col);
bool check(vector<vector<string>>& relation, vector<int> col);
int solution(vector<vector<string>> relation);
bool comp(vector<int> a, vector<int> b) { return a[0] < b[0]; }
bool colChecked[16];
vector<vector<int>> ansVec;
int main() {
//각각 2, 1, 2, 1 ,5 가 나와야함
vector<vector<string>> relation = { {"100","ryan","music","2"},{"200","apeach","math","2"},{"300","tube","computer","3"},{"400","con","computer","4"},{"500","muzi","music","3"},{"600","apeach","music","2"} };
vector<vector<string>> relation2 = { {"a","b","c"}, {"1","b","c"}, {"a","b","4"}, {"a","5","c"} };
vector<vector<string>> relation3 = { {"a","1","4"}, {"2","1","5"}, {"a","2","4"} };
vector<vector<string>> relation4 = { {"a","aa"}, {"aa","a"}, {"a","a"} };
vector<vector<string>> relation5 = { {"b","2","a","a","b"},
{"b","2","7","1","b"},
{"1","0","a","a","8"},
{"7","5","a","a","9"},
{"3","0","a","f","9"} };
solution(relation4);
}
int solution(vector<vector<string>> relation) {
int answer = 0;
for (int i = 0; i < relation[0].size(); i++) {
colChecked[i] = true;
DFS(relation, vector<int>(1,i));
colChecked[i] = false;
}
//check overlapping element
sort(ansVec.begin(), ansVec.end(), comp);
for (int i = 0; i < ansVec.size(); i++) {
for (int j = i + 1; j < ansVec.size(); j++)
{
int count = 0;
for (int k = 1; k < 16; k++) {
if (ansVec[i][k] == 1 && ansVec[j][k] == 1 ) count++;
}
if (count == ansVec[i][0] && count != 0)
ansVec[j][0] = 0;
}
}
for (int i = 0; i < ansVec.size(); i++) {
if (ansVec[i][0] != 0)
answer++;
}
return answer;
}
void DFS(vector<vector<string>> &relation, vector<int> col) {
//col check implement
if (col.size() > relation[0].size())
return;
if (check(relation, col))
return;
for (int i = col.back() + 1; i < relation[0].size();i++) {
if (colChecked[i] == true) continue;
colChecked[i] = true;
col.push_back(i);
//checked out and add new col
DFS(relation, col);
colChecked[i] = false;
col.pop_back();
}
}
bool check(vector<vector<string>> &relation, vector<int>col) {
//check if relation with selected col could be primary key
vector<string> myVec;
for (int i = 0; i < relation.size(); i++) {
string strtemp ="";
for (int j = 0; j < col.size(); j++) {
strtemp += relation[i][col[j]] + " ";
}
auto iter = find(myVec.begin(), myVec.end(), strtemp);
if (iter == myVec.end())
myVec.push_back(strtemp);
else
return false;
}
vector<int> temp(16, 0);
temp[0] = col.size();
for (size_t i = 0; i < col.size(); i++)
temp[col[i] + 1] = 1;
ansVec.push_back(temp);
return true;
}
최소성에 대한 부분을 여러번 고쳤다. 다른 사람들의 풀이를 보면 대부분의 실패 원인은 최소성에 관한 코드에서 발생한다.
카카오는 전반적으로 문제 설명이 깔끔하고 예제를 잘 보여주며, 구현능력을 상당히 중요하게 생각한다는 느낌을 받았다.