[ν”„λ‘œκ·Έλž˜λ¨ΈμŠ€] 후보킀 :: C++, SQL, μ½”λ“œ, 풀이 (μ£Όμ˜ν•  점!)

후보킀

문제

문제 μ„€λͺ…

후보킀

ν”„λ Œμ¦ˆλŒ€ν•™κ΅ 컴퓨터곡학과 쑰ꡐ인 μ œμ΄μ§€λŠ” λ„€μ˜€ ν•™κ³Όμž₯λ‹˜μ˜ μ§€μ‹œλ‘œ, ν•™μƒλ“€μ˜ 인적사항을 μ •λ¦¬ν•˜λŠ” 업무λ₯Ό λ‹΄λ‹Ήν•˜κ²Œ λ˜μ—ˆλ‹€.

그의 ν•™λΆ€ μ‹œμ ˆ ν”„λ‘œκ·Έλž˜λ° κ²½ν—˜μ„ λ˜μ‚΄λ €, λͺ¨λ“  인적사항을 λ°μ΄ν„°λ² μ΄μŠ€μ— λ„£κΈ°λ‘œ ν•˜μ˜€κ³ , 이λ₯Ό μœ„ν•΄ 정리λ₯Ό ν•˜λ˜ 쀑에 후보킀(Candidate Key)에 λŒ€ν•œ 고민이 ν•„μš”ν•˜κ²Œ λ˜μ—ˆλ‹€.

후보킀에 λŒ€ν•œ λ‚΄μš©μ΄ 잘 κΈ°μ–΅λ‚˜μ§€ μ•Šλ˜ μ œμ΄μ§€λŠ”, μ •ν™•ν•œ λ‚΄μš©μ„ νŒŒμ•…ν•˜κΈ° μœ„ν•΄ λ°μ΄ν„°λ² μ΄μŠ€ κ΄€λ ¨ μ„œμ μ„ ν™•μΈν•˜μ—¬ μ•„λž˜μ™€ 같은 λ‚΄μš©μ„ ν™•μΈν•˜μ˜€λ‹€.

  • 관계 λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ λ¦΄λ ˆμ΄μ…˜(Relation)의 νŠœν”Œ(Tuple)을 μœ μΌν•˜κ²Œ 식별할 수 μžˆλŠ” 속성(Attribute) λ˜λŠ” μ†μ„±μ˜ 집합 쀑, λ‹€μŒ 두 μ„±μ§ˆμ„ λ§Œμ‘±ν•˜λŠ” 것을 후보 ν‚€(Candidate Key)라고 ν•œλ‹€.
    • μœ μΌμ„±(uniqueness) : λ¦΄λ ˆμ΄μ…˜μ— μžˆλŠ” λͺ¨λ“  νŠœν”Œμ— λŒ€ν•΄ μœ μΌν•˜κ²Œ μ‹λ³„λ˜μ–΄μ•Ό ν•œλ‹€.
    • μ΅œμ†Œμ„±(minimality) : μœ μΌμ„±μ„ 가진 ν‚€λ₯Ό κ΅¬μ„±ν•˜λŠ” 속성(Attribute) 쀑 ν•˜λ‚˜λΌλ„ μ œμ™Έν•˜λŠ” 경우 μœ μΌμ„±μ΄ κΉ¨μ§€λŠ” 것을 μ˜λ―Έν•œλ‹€. 즉, λ¦΄λ ˆμ΄μ…˜μ˜ λͺ¨λ“  νŠœν”Œμ„ μœ μΌν•˜κ²Œ μ‹λ³„ν•˜λŠ” 데 κΌ­ ν•„μš”ν•œ μ†μ„±λ“€λ‘œλ§Œ κ΅¬μ„±λ˜μ–΄μ•Ό ν•œλ‹€.

μ œμ΄μ§€λ₯Ό μœ„ν•΄, μ•„λž˜μ™€ 같은 ν•™μƒλ“€μ˜ 인적사항이 μ£Όμ–΄μ‘Œμ„ λ•Œ, 후보 ν‚€μ˜ μ΅œλŒ€ 개수λ₯Ό κ΅¬ν•˜λΌ.

cand_key1.png

μœ„μ˜ 예λ₯Ό μ„€λͺ…ν•˜λ©΄, ν•™μƒμ˜ 인적사항 λ¦΄λ ˆμ΄μ…˜μ—μ„œ λͺ¨λ“  학생은 각자 μœ μΌν•œ ν•™λ²ˆμ„ 가지고 μžˆλ‹€. λ”°λΌμ„œ ν•™λ²ˆμ€ λ¦΄λ ˆμ΄μ…˜μ˜ 후보 ν‚€κ°€ 될 수 μžˆλ‹€.
κ·Έλ‹€μŒ 이름에 λŒ€ν•΄μ„œλŠ” 같은 이름(apeach)을 μ‚¬μš©ν•˜λŠ” 학생이 있기 λ•Œλ¬Έμ—, 이름은 후보 ν‚€κ°€ 될 수 μ—†λ‹€. κ·ΈλŸ¬λ‚˜, λ§Œμ•½ [이름, 전곡]을 ν•¨κ»˜ μ‚¬μš©ν•œλ‹€λ©΄ λ¦΄λ ˆμ΄μ…˜μ˜ λͺ¨λ“  νŠœν”Œμ„ μœ μΌν•˜κ²Œ 식별 κ°€λŠ₯ν•˜λ―€λ‘œ 후보 ν‚€κ°€ 될 수 있게 λœλ‹€.
λ¬Όλ‘  [이름, 전곡, ν•™λ…„]을 ν•¨κ»˜ μ‚¬μš©ν•΄λ„ λ¦΄λ ˆμ΄μ…˜μ˜ λͺ¨λ“  νŠœν”Œμ„ μœ μΌν•˜κ²Œ 식별할 수 μžˆμ§€λ§Œ, μ΅œμ†Œμ„±μ„ λ§Œμ‘±ν•˜μ§€ λͺ»ν•˜κΈ° λ•Œλ¬Έμ— 후보 ν‚€κ°€ 될 수 μ—†λ‹€.
λ”°λΌμ„œ, μœ„μ˜ 학생 μΈμ μ‚¬ν•­μ˜ ν›„λ³΄ν‚€λŠ” ν•™λ²ˆ, [이름, 전곡] 두 κ°œκ°€ λœλ‹€.

λ¦΄λ ˆμ΄μ…˜μ„ λ‚˜νƒ€λ‚΄λŠ” λ¬Έμžμ—΄ λ°°μ—΄ relation이 λ§€κ°œλ³€μˆ˜λ‘œ μ£Όμ–΄μ§ˆ λ•Œ, 이 λ¦΄λ ˆμ΄μ…˜μ—μ„œ 후보 ν‚€μ˜ 개수λ₯Ό return ν•˜λ„λ‘ solution ν•¨μˆ˜λ₯Ό μ™„μ„±ν•˜λΌ.

μ œν•œμ‚¬ν•­

  • relation은 2차원 λ¬Έμžμ—΄ 배열이닀.
  • relation의 컬럼(column)의 κΈΈμ΄λŠ” 1 이상 8 μ΄ν•˜μ΄λ©°, 각각의 μ»¬λŸΌμ€ λ¦΄λ ˆμ΄μ…˜μ˜ 속성을 λ‚˜νƒ€λ‚Έλ‹€.
  • relation의 둜우(row)의 κΈΈμ΄λŠ” 1 이상 20 μ΄ν•˜μ΄λ©°, 각각의 λ‘œμš°λŠ” λ¦΄λ ˆμ΄μ…˜μ˜ νŠœν”Œμ„ λ‚˜νƒ€λ‚Έλ‹€.
  • relation의 λͺ¨λ“  λ¬Έμžμ—΄μ˜ κΈΈμ΄λŠ” 1 이상 8 μ΄ν•˜μ΄λ©°, μ•ŒνŒŒλ²³ μ†Œλ¬Έμžμ™€ 숫자둜만 이루어져 μžˆλ‹€.
  • relation의 λͺ¨λ“  νŠœν”Œμ€ μœ μΌν•˜κ²Œ 식별 κ°€λŠ₯ν•˜λ‹€.(즉, μ€‘λ³΅λ˜λŠ” νŠœν”Œμ€ μ—†λ‹€.)

μž…μΆœλ ₯ 예

relation result
[["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

μž…μΆœλ ₯ 예 μ„€λͺ…

μž…μΆœλ ₯ 예 #1
λ¬Έμ œμ— 주어진 λ¦΄λ ˆμ΄μ…˜κ³Ό κ°™μœΌλ©°, 후보 ν‚€λŠ” 2κ°œμ΄λ‹€.


μ½”λ“œ

#include <string>
#include <vector>
#include <set>
#include <algorithm>

using namespace std;

bool compare(string a, string b) {
    return a.length() < b.length();
}

int solution(vector<vector<string>> relation) {
    int answer = 0;
    int row = relation.size();
    int column = relation[0].size();
    vector<string> memorize;
    vector<int> permutation;

    for (int i = 0; i<column; i++)
        permutation.push_back(i);

    for (int i = 1; i <= column; i++) {
        pair<set<string>::iterator, bool> ret;
        vector<int> bitMap(column, 0);

        for (int j = 0; j<i; j++) {
            bitMap[j] = 1;
        }
        sort(bitMap.begin(), bitMap.end()); // next_permutation은 sortλ˜μ–΄μžˆμ–΄μ•Όν•œλ‹€λŠ” 것 λͺ…심!

        do {
            vector<int> columnNum;
            for (int j = 0; j<column; j++) {
                if (bitMap[j] == 1) {
                    columnNum.push_back(permutation[j]);
                }
            }
            if (columnNum.size() == 0)
                break;

            int flag = 1;
            set<string> stringSet;
            for (int j = 0; j<row; j++) {
                string tmpStr = "";
                for (int k = 0; k<columnNum.size(); k++) {
                    tmpStr += relation[j][columnNum[k]];
                }
                ret = stringSet.insert(tmpStr);
                if (ret.second == false) {
                    flag = 0;
                    break;
                }
            }
            if (flag) {
                string pair;
                for (int j = 0; j<columnNum.size(); j++) {
                    pair += to_string(columnNum[j]);
                }
                flag = 1;
                for (int j = 0; j < memorize.size(); j++) {
                    if (includes(pair.begin(), pair.end(), memorize[j].begin(), memorize[j].end())) { // ν¬ν•¨λ˜μ–΄μžˆλ‹€λ©΄
                        flag = 0;
                        break;
                    }
                }
                if (flag) {
                    memorize.push_back(pair);
                }
            }
        } while (next_permutation(bitMap.begin(), bitMap.end()));
    }
    answer = memorize.size();
    return answer;
}

 

풀이

μš°μ„ , μž…λ ₯의 μ΅œλŒ“κ°’μ΄ 8이기 λ•Œλ¬Έμ— column에 λŒ€ν•œ 쑰합을 찾아도 μ‹œκ°„λ³΅μž‘λ„μ—λŠ” 이상이 μ—†μŒμ„ ν™•μΈν•˜μ˜€λ‹€.

  1. column의 쑰합을 찾자.
  2. μ‘°ν•©λ³„λ‘œ rowλ₯Ό νƒμƒ‰ν•˜λ©°, uniqueν•œ 쑰합은 μ €μž₯ν•˜μž.
  3. 이 λ•Œ, 쑰합은 μ΅œμ†Œμ„±μ„ μœ μ§€ν•΄μ•Όν•˜λ―€λ‘œ λ‹€λ₯Έ μ‘°ν•©μ˜ 뢀뢄집합이 μ•„λ‹ˆμ–΄μ•Όν•œλ‹€.

μ΄λŸ¬ν•œ 사고과정을 κ±°μ³μ„œ 문제λ₯Ό ν•΄κ²°ν•˜μ˜€λ‹€. μžμ„Έν•œ 풀이λ₯Ό μ‚΄νŽ΄λ³΄μž.

  1. column의 쑰합을 μ°ΎκΈ° μœ„ν•΄ next_permutation ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜μ˜€λ‹€. next_permutation ν•¨μˆ˜μ™€ bitmap을 μ΄μš©ν•˜λ©΄ μˆœμ—΄ν•¨μˆ˜λ‘œ 쑰합을 찾을 수 μžˆλ‹€.
  2. uniqueν•œ column쑰합을 μ°ΎκΈ° μœ„ν•΄μ„œ row λ³„λ‘œ column 쑰합에 ν•΄λ‹Ήν•˜λŠ” 값을 string으둜 λ¬Άμ–΄μ€€ ν›„, set 자료ꡬ쑰λ₯Ό μ΄μš©ν•΄μ„œ 쀑볡 값이 μ—†λŠ” column 쑰합을 μ°Ύμ•˜λ‹€.
  3. 뢀뢄집합을 νŒλ‹¨ν•˜λŠ” 뢀뢄은 includes ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜μ˜€λ‹€.

 

채점결과

 

μ£Όμ˜μ‚¬ν•­

  • μ–΄λ–€ μΉœμ ˆν•œ 뢄이 μ§ˆλ¬Έν•˜κΈ°μ— 남겨주셨듯이, string을 ν¬ν•¨ν•˜λŠ”μ§€λ₯Ό 물을 λ•Œ find ν•¨μˆ˜λ₯Ό μ“°λ©΄ 뢀뢄집합관계λ₯Ό μž‘μ•„λ‚΄μ§€ λͺ»ν•œλ‹€.
    • ex_ "abcd" μ•ˆμ— "ad"κ°€ 포함됨을 λ‚˜νƒ€λ‚΄λ €λ©΄ includes(str1.begin(), str1.end(), str2.begin(), str2.end()) ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ•Όν•¨
  • next_permutation은 μ˜€λ¦„μ°¨μˆœ sortλ˜μ–΄μžˆμ–΄μ•Όν•œλ‹€λŠ” 것 λͺ…심할 것
  • 같은 κ±Έ μž‘μ•„λ‚΄λ €λ©΄ set μžλ£Œκ΅¬μ‘°λ³΄λ‹€λŠ” findλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 μ’‹λ‹€. => 같은 idx도 찾을 수 있기 λ•Œλ¬Έ
    • idxκ°€ ν•„μš”μ—†μœΌλ©΄ set을 μ“°λŠ” 것이 더 κ°„νŽΈν•˜λ‹€.
    • λ¦¬ν„΄κ°’μ—μ„œ 1번째 μΈμžλŠ” iterator, 2번째 μΈμžκ°€ booleanμž„μ„ μžŠμ§€λ§μž.
λ°˜μ‘ν˜•