프로그래머스 SQL 고득점 KIT

출처

SELECT

59034 - 모든 레코드 조회하기

문제 링크

SELECT * FROM ANIMAL_INS ORDER BY ANIMAL_ID ASC

59035 - 역순 정렬하기

문제 링크

SELECT NAME, DATETIME FROM ANIMAL_INS ORDER BY ANIMAL_ID DESC

59036 - 아픈 동물 찾기

문제 링크

SELECT ANIMAL_ID, NAME FROM ANIMAL_INS WHERE INTAKE_CONDITION="Sick"

59037 - 어린 동물 찾기

문제 링크

SELECT ANIMAL_ID, NAME FROM ANIMAL_INS WHERE INTAKE_CONDITION!="Aged"

59403 - 동물의 아이디와 이름

문제 링크

SELECT ANIMAL_ID, NAME FROM ANIMAL_INS

59404 - 여러 기준으로 정렬하기

문제 링크

SELECT ANIMAL_ID, NAME, DATETIME FROM ANIMAL_INS ORDER BY NAME ASC, DATETIME DESC

59405 - 상위 n개 레코드

문제 링크

SELECT NAME FROM ANIMAL_INS ORDER BY DATETIME ASC LIMIT 1

SUM, MAX, MIN

59415 - 최댓값 구하기

문제 링크

SELECT MAX(DATETIME) AS 시간 FROM ANIMAL_INS

59038 - 최솟값 구하기

문제 링크

SELECT MIN(DATETIME) AS 시간 FROM ANIMAL_INS

59406 - 동물 수 구하기

문제 링크

SELECT COUNT(*) AS 동물수 FROM ANIMAL_INS

59408 - 중복 제거하기

문제 링크

SELECT COUNT(DISTINCT NAME) AS 동물수 FROM ANIMAL_INS WHERE NAME IS NOT NULL

GROUP BY

59040 - 고양이와 개는 몇 마리 있을까

문제 링크

SELECT ANIMAL_TYPE, COUNT(*) AS 'count' FROM ANIMAL_INS GROUP BY ANIMAL_TYPE ORDER BY ANIMAL_TYPE ASC 

59041 - 동명 동물 수 찾기

문제 링크

SELECT NAME, COUNT(*) AS 'COUNT' FROM ANIMAL_INS GROUP BY NAME HAVING COUNT(NAME) >= 2 ORDER BY NAME

59412 - 입양 시각 구하기 (1)

문제 링크

SELECT HOUR(DATETIME) AS 'HOUR', COUNT(*) AS 'COUNT'
FROM ANIMAL_OUTS
GROUP BY HOUR(DATETIME)
HAVING HOUR >= 9 AND HOUR <= 19
ORDER BY HOUR(DATETIME) ASC

59413 - 입양 시각 구하기 (2)

문제 링크

SET @hour := -1;

SELECT (@hour := @hour + 1) as HOUR,
    (SELECT COUNT(*) FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = @hour) as COUNT
FROM ANIMAL_OUTS
WHERE @hour < 23

IS NULL

59039 - 이름이 없는 동물의 이야기

문제 링크

SELECT ANIMAL_ID FROM ANIMAL_INS WHERE NAME IS NULL

59407 - 이름이 있는 동물의 아이디

문제 링크

SELECT ANIMAL_ID FROM ANIMAL_INS WHERE NAME IS NOT NULL

59410 - NULL 처리하기

문제 링크

SELECT ANIMAL_TYPE, IF(NAME IS NULL, 'No name', NAME) AS NAME, SEX_UPON_INTAKE 
FROM ANIMAL_INS

JOIN

59042 - 없어진 기록 찾기

문제 링크

SELECT b.ANIMAL_ID, b.NAME
FROM ANIMAL_INS a RIGHT JOIN ANIMAL_OUTS b on a.ANIMAL_ID = b.ANIMAL_ID
WHERE a.ANIMAL_ID IS NULL
ORDER BY b.ANIMAL_ID

59043 - 있었는데요 없었습니다

문제 링크

SELECT b.ANIMAL_ID, b.NAME
FROM ANIMAL_INS a RIGHT JOIN ANIMAL_OUTS b on a.ANIMAL_ID = b.ANIMAL_ID
WHERE a.ANIMAL_ID IS NOT NULL AND a.DATETIME > b.DATETIME
ORDER BY a.DATETIME

59044 - 오랜 기간 보호한 동물(1)

문제 링크

SELECT ANIMAL_INS.NAME, ANIMAL_INS.DATETIME
FROM ANIMAL_INS
    LEFT OUTER JOIN ANIMAL_OUTS 
    ON ANIMAL_INS.ANIMAL_ID = ANIMAL_OUTS.ANIMAL_ID
WHERE ANIMAL_OUTS.ANIMAL_ID IS NULL
ORDER BY ANIMAL_INS.DATETIME ASC
LIMIT 3

59045 - 보호소에서 중성화한 동물

문제 링크

SELECT ANIMAL_INS.ANIMAL_ID, ANIMAL_INS.ANIMAL_TYPE, ANIMAL_INS.NAME
FROM ANIMAL_INS
    LEFT OUTER JOIN ANIMAL_OUTS 
    ON ANIMAL_INS.ANIMAL_ID = ANIMAL_OUTS.ANIMAL_ID
WHERE ANIMAL_INS.SEX_UPON_INTAKE != ANIMAL_OUTS.SEX_UPON_OUTCOME

String, Date

59046 루시와 엘라 찾기

문제 링크

SELECT ANIMAL_ID, NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS
WHERE NAME = 'Lucy' OR NAME = 'Ella' OR NAME = 'Pickle' OR NAME = 'Rogan' OR NAME = 'Sabrina' OR NAME = 'Mitty'
SELECT ANIMAL_ID, NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS 
WHERE NAME IN ('Lucy', 'Ella', 'Pickle', 'Rogan', 'Sabrina', 'Mitty')

59047 - 이름에 el이 들어가는 동물 찾기

문제 링크

SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
WHERE UPPER(NAME) LIKE "%EL%" AND ANIMAL_TYPE = "Dog"
ORDER BY NAME ASC

59409 - 중성화 여부 파악하기

문제 링크

SELECT ANIMAL_ID, NAME,
    IF(SEX_UPON_INTAKE LIKE "%Neutered%" OR SEX_UPON_INTAKE LIKE "%Spayed%", 'O', 'X') AS '중성화'
FROM ANIMAL_INS
ORDER BY ANIMAL_ID ASC

59411 - 오랜 기간 보호한 동물 (2)

문제 링크

SELECT ANIMAL_INS.ANIMAL_ID, ANIMAL_INS.NAME
FROM ANIMAL_INS, ANIMAL_OUTS
WHERE ANIMAL_INS.ANIMAL_ID = ANIMAL_OUTS.ANIMAL_ID
ORDER BY ANIMAL_OUTS.DATETIME - ANIMAL_INS.DATETIME DESC
LIMIT 2

59414 - DATETIME에서 DATE로 형 변환

문제 링크

SELECT ANIMAL_ID, NAME, DATE_FORMAT(DATETIME, '%Y-%m-%d') AS 날짜
FROM ANIMAL_INS
ORDER BY ANIMAL_ID ASC

기타 유용한 함수들

  • DATEDIFF(날짜1, 날짜2) : 날짜1과 날짜2의 날짜 차이를 구할 수 있음
  • ABS(숫자) : 숫자의 절댓값
  • DATE_FORMAT(날짜, '%Y-%m-%d %t') : 날짜의 형식을 바꿉니다.
  • IF(조건, 값1, 값2) : 조건이 참이면 값1, 거짓이면 값2

프로그래머스 42890 - 후보키

문제 링크

생각 및 접근

  • DB의 개념인 후보키의 갯수를 구하는 문제였다.

  • 내 수도 코드는 이렇다.

    • 조합(dfs)을 통해서 칼럼의 갯수를 1부터 칼럼의 갯수까지 칼럼의 인덱스를 고른다.
    • 인덱스를 다 골랐다면, 기존에 후보키였던 것을 포함하는지 검사한다.
      • 기존에 후보키였던 것을 포함한다면, 지금 검사하는 칼럼의 인덱스는 최소성을 만족하지 못하므로 return
      • 기존에 후보키였던 것을 포함하지 않는다면,
        • vector<vector<string>> relation의 모든 레코드에 대해 칼럼의 인덱스의 값들을 추출해서, 한 vector<string>으로 잡는다. 잡은 vector<string>vector<vector<string>>에 넣는다.
        • 모두 넣고, 일일히 대조해서 처음부터 끝까지 일치하는지 확인한다.
          • 일치하는게 있다면, 후보키가 되지 못하므로 return
          • 일치하는게 없다면, 후보키가 될 수 있다.
  • 조금 말이 어려운데, 코드를 보면서 이해해보자.

  • 아래 코드는 후보키의 가짓수를 토대로 dfs를 돌리는 함수다.

      vector<vector<string>> rel;
    
      // answer는 후보키의 vector를 저장한다.
      vector<vector<int>> answer;
      int col, row, arr[21];
    
      int solution(vector<vector<string>> relation) {
          row = relation.size();
          col = relation[0].size();
          rel = relation;
    
          // i는 후보키의 가짓수
          for(int i = 1; i <= col; i++){
              // arr은 칼럼의 인덱스를 저장할 예정.
              memset(arr, 0, sizeof(arr));
              dfs(i, 0, -1);
          }
    
          return answer.size();
      }
  • 아래 코드는 조합을 시행하는 dfs다.

      // 벡터 a와 벡터 b가 모두 같은 원소를 가지고 있는지 판단하는 함수다.
      bool vector_is_equal(vector<string> a, vector<string> b){
          int vec_size = a.size();
          for(int i = 0; i < vec_size; i++){
              if(a[i] != b[i])    return false;
          }
          return true;
      }
    
      // goal : 나는 인덱스를 goal개 만큼 집기로 했다.
      // cnt : 나는 인덱스를 cnt개 만큼 집었다.
      // idx : 나는 인덱스를 idx까지 골랐었다.
      void dfs(int goal, int cnt, int idx){
          // 조합을 통해 모두 집었다면,
          if(goal == cnt){
    
              // 기존에 찾아놓은 후보키를 포함하고 있는 지 검사
              for(auto i : answer){
                  int ans_idx = 0;
                  for(int j = 0; j < goal; j++){
                      if(i[ans_idx] == arr[j])    ans_idx++;
                      if(ans_idx >= i.size())     break;
                  }
                  if(ans_idx >= i.size()) return;
              }
    
              // 후보키가 될 수 있는지 검사할 예정
              // vector<vector<string>> relation에서 골라놓은 인덱스를 저장해놓은 arr에 존재하는 인덱스대로 하나의 tmp 벡터를 만들고, 이를 cmp 벡터에 넣어준다.
              vector<vector<string>> cmp;
              for(int i = 0; i < row; i++){
                  vector<string> tmp;
                  for(int j = 0; j < goal; j++)
                      tmp.push_back(rel[i][arr[j]]);
                  cmp.push_back(tmp);
              }
    
              // 비교하는 과정
              for(int i = 0; i < row; i++){
                  for(int j = i + 1; j < row; j++){
                      // 벡터가 하나라도 같은 게 있으면 후보키가 되지 못함
                      if(vector_is_equal(cmp[i], cmp[j]))  return;
                  }
              }
    
              // 벡터가 모두 다르므로 후보키가 될 수 있다.
              vector<int> answer_temp;
              for(int i = 0; i < goal; i++)
                  answer_temp.push_back(arr[i]);
              answer.push_back(answer_temp);
          }
    
          // 다음 조합 진행
          else {
              for(int i = idx + 1; i < col; i++){
                  arr[cnt] = i;
                  dfs(goal, cnt + 1, i);
              }
          }
      }

코드

#include <bits/stdc++.h>
using namespace std;

vector<vector<string>> rel;
vector<vector<int>> answer;
int col, row, arr[21];

bool vector_is_equal(vector<string> a, vector<string> b){
    int vec_size = a.size();
    for(int i = 0; i < vec_size; i++){
        if(a[i] != b[i])    return false;
    }
    return true;
}

void dfs(int goal, int cnt, int idx){
    if(goal == cnt){
        for(auto i : answer){
            int ans_idx = 0;
            for(int j = 0; j < goal; j++){
                if(i[ans_idx] == arr[j])    ans_idx++;
                if(ans_idx >= i.size())     break;
            }
            if(ans_idx >= i.size()) return;
        }

        vector<vector<string>> cmp;
        for(int i = 0; i < row; i++){
            vector<string> tmp;
            for(int j = 0; j < goal; j++)
                tmp.push_back(rel[i][arr[j]]);
            cmp.push_back(tmp);
        }

        for(int i = 0; i < row; i++){
            for(int j = i + 1; j < row; j++){
                if(vector_is_equal(cmp[i], cmp[j]))  return;
            }
        }

        vector<int> answer_temp;
        for(int i = 0; i < goal; i++)
            answer_temp.push_back(arr[i]);
        answer.push_back(answer_temp);
    }
    else {
        for(int i = idx + 1; i < col; i++){
            arr[cnt] = i;
            dfs(goal, cnt + 1, i);
        }
    }
}

int solution(vector<vector<string>> relation) {
    row = relation.size();
    col = relation[0].size();
    rel = relation;

    for(int i = 1; i <= col; i++){
        memset(arr, 0, sizeof(arr));
        dfs(i, 0, -1);
    }

    return answer.size();
}

채점 결과

프로그래머스 42889 - 실패율

문제 링크

생각 및 접근

  • struct를 다루는 것이 관건이 된 문제다.
  • 문제 해결의 구조
    • 우선, 아래 struct StageN개 담고 있는 vector를 만든다. (v)
    • 문제에서 주어진 stages를 순회한다.
      • 만약 stages[i] > N (즉, 이 유저가 고인물이라면)
        • 이 유저는 1부터 N까지의 모든 스테이지를 통과한 것이 된다. 따라서, Stage의 idx 1 ~ N 까지의 성공 유저 수를 하나씩 늘린다.
      • 만약 stages[i] <= N (즉, 이 유저가 뉴비라면)
        • 이 유저는 1부터 stages[i] - 1까지 통과한 것이고, stages[i]를 실패한 상태
          • 따라서 Stage의 idx 1 ~ stages[i] - 1까지의 성공 유저 수를 하나씩 늘리고,
          • Stage의 idx stages[i]의 실패 유저 수를 하나씩 늘린다.
    • 순회가 끝나면, 실패율을 계산해서 실패율 내림차순 -> 스테이지 단계 오름차순 순으로 정렬한다.
    • 정렬이 끝난 v의 각 Stage의 단계 번호를 answer에 담아 반환한다.
  • struct Stage
    • int idx : 각 단계의 번호를 의미
    • int s : success한 유저의 수
    • int f : fail한 유저의 수
    • float rate : 실패율
    • void setS() : s를 하나 늘려준다.
    • void setF() : f를 하나 늘려준다.
    • void calcRate() : 실패율을 계산해서 rate에 저장한다. 식은 rate = (float) f / (float) (s + f);인데, s + f가 0일 때 주의하자.
    • 나중에 정렬을 할건데, 제일 우선되는건 실패율 내림차순, 그 다음은 단계의 번호로 오름차순이 되겠다.
        bool operator < (const Stage & b) const {
            if(rate == b.rate){
                return idx < b.idx;
            }
            return rate > b.rate;
        }

코드

#include <bits/stdc++.h>
using namespace std;

struct Stage{
    int idx;
    int s;
    int f;
    float rate;
    Stage(int i, int a, int b){
        idx = i; s = a; f = b; rate = 0;
    }
    void setS(){
        s++;
    }
    void setF(){
        f++;
    }
    void calcRate(){
        if(s + f == 0){
            rate = 0;
        }
        else{
            rate = (float) f / (float) (s + f);    
        }
    }
    bool operator < (const Stage & b) const {
        if(rate == b.rate){
            return idx < b.idx;
        }
        return rate > b.rate;
    }
};

vector<int> answer;
vector<Stage> v;

vector<int> solution(int N, vector<int> stages) {
    for(int i = 1; i <= N; i++)
        v.push_back(Stage(i, 0, 0));

    for(int i = 0; i < stages.size(); i++){
        if(stages[i] > N){
            for(int j = 0; j <= N - 1; j++)
                v[j].setS();
        }
        else {
            for(int j = 0; j <= stages[i] - 2; j++)
                v[j].setS();
            v[stages[i] - 1].setF();
        }
    }

    for(int i = 0; i < N; i++)  v[i].calcRate();
    sort(v.begin(), v.end());

    for(int i = 0; i < N; i++)  answer.push_back(v[i].idx);
    return answer;
}

채점 결과


프로그래머스 42888 - 오픈채팅방

문제 링크

생각 및 접근

  • vector<pair<string, string>> logs;

    • 유저들이 나가거나, 들어오거나를 기록하는 logs
    • 앞의 string은 uid를, 뒤의 string은 Enter, 혹은 Leave를 저장할 예정
  • map<string, string> m;

    • 유저들의 이름을 저장할 map 선언
    • 앞의 string은 uid를, 뒤의 string은 유저들의 닉네임을 저장.
  • 주어진 vector<string> record를 분석한다.

    • action[0]에는 행동을 담았다. (Leave, Enter, Change)
    • action[1]에는 uid를 담았다.
    • action[2]에는 유저들의 닉네임을 담았다.
    • 만약 행동이 떠나거나, 들어오는 것이었다면 logs에 저장해두어야 한다.
        if(action[ACT] == "Enter" || action[ACT] == "Leave"){
            logs.push_back(make_pair(action[ID], action[ACT]));
        }
    • 만약 행동이 들어오거나, 이름을 바꾸는 행위라면, 닉네임이 바뀌었을 수 있기 때문에, m을 바꿔준다.
        if(action[ACT] == "Enter" || action[ACT] == "Change"){
            m[action[ID]] = action[NAME];
        }
  • 최종적으로 answer의 형태로 변환하기 위해, 아래 코드와 같은 과정을 거친다.

      lSize = logs.size();
      for(int i = 0; i < lSize; i++){
          string temp = m[logs[i].first];
          if(logs[i].second == "Enter")
              temp.append("님이 들어왔습니다.");
          else
              temp.append("님이 나갔습니다.");
          answer.push_back(temp);
      }
    
      return answer;

코드

#include <bits/stdc++.h>
#define ACT 0
#define ID 1
#define NAME 2
using namespace std;

vector<string> answer;
vector<pair<string, string>> logs;
map<string, string> m;

vector<string> solution(vector<string> record) {
    int rSize = record.size();
    int lSize;
    for(int i = 0; i < rSize; i++){
        int k = 0;
        string action[3];
        for(int j = 0; record[i][j] != '\0'; j++){
            if(record[i][j] == ' ') k++;
            else    action[k].push_back(record[i][j]);
        }

        if(action[ACT] == "Enter" || action[ACT] == "Leave"){
            logs.push_back(make_pair(action[ID], action[ACT]));
        }

        if(action[ACT] == "Enter" || action[ACT] == "Change"){
            m[action[ID]] = action[NAME];
        }
    }

    lSize = logs.size();
    for(int i = 0; i < lSize; i++){
        string temp = m[logs[i].first];
        if(logs[i].second == "Enter")
            temp.append("님이 들어왔습니다.");
        else
            temp.append("님이 나갔습니다.");
        answer.push_back(temp);
    }

    return answer;
}

채점 결과

프로그래머스 42628 - 이중우선순위큐

문제 링크

생각 및 접근

  • 이중우선순위큐라고 해서 우선순위 큐를 활용해야 될 것 같았지만, 문제를 분석하다 보니 그냥 vector로 풀어도 상관없겠다는 판단이 났다.
  • operations 돌리기
    • I 숫자라면 vector에 삽입
    • D 1이라면 내림차순으로 나열해서 pop_back()
    • D -1이라면 오름차순으로 나열해서 pop_back()

코드

#include <bits/stdc++.h>
using namespace std;

vector<int> solution(vector<string> operations) {
    vector<int> q;
    for(auto o : operations){
        if(o[0] == 'I'){
            string temp = o.substr(2);
            q.push_back(stoi(temp));
        }
        else if(!q.empty() && o == "D 1"){
            if(q.size() != 1)    sort(q.begin(), q.end());
            q.pop_back();
        }
        else if(!q.empty() && o == "D -1"){
            if(q.size() != 1)    sort(q.rbegin(), q.rend());
            q.pop_back();
        }
    }

    sort(q.begin(), q.end());
    vector<int> answer;
    if(q.empty()){
        answer.push_back(0);
        answer.push_back(0);
    }
    else{
        answer.push_back(q[q.size() - 1]);
        answer.push_back(q[0]);
    }
    return answer;
}

채점 결과

프로그래머스 42629 - 라면공장

문제 링크

생각 및 접근

사족

  • 나는 이런 문제에 약한 것 같다. 날짜와 데이터가 섞여서 최적의 결과를 나타내는 문제들. 연습을 좀 해야겠다.

본론

  • dates와 supplies를 묶어서 관리하기 위해 새로운 구조체 Data를 하나 선언한다.

      struct Data{
          int date;
          int supply;
          Data(int a, int b): date(a), supply(b) {}
      };
  • 밀가루를 공급받기 위해 판단의 기준이 되는 우선순위 큐 pq 하나와, 밀가루를 공급받기 위한 날짜의 후보를 넣어두는 큐 q 하나를 선언한다.

    • 우선순위 큐

        priority_queue<Data, vector<Data>, cmp> pq;
    •   queue<Data> q;
        for(int i = 0; i < dates.size(); i++)
            q.push(Data(dates[i], supplies[i]));
  • 후보들은 q에서 대기하고 있다가, pq에 넣어질 수 있는 조건이 충족되면 그때서야 pq에 넣어진다.

    • 조건

      • 내가 가지고 있는 밀가루 양보다 q.front().date가 작아야 한다.

      • why : 공장의 운영이 끊기면 안된다. 밀가루 양 currentcurrent일까지 공장이 운영될 수 있는 날이고, 밀가루는 미리 받아놓거나 (current > q.front().date인 경우) 밀가루가 떨어진 바로 다음날 새벽 (current = q.front().date인 경우) 에 받을 수 있기 때문에, 다음과 같은 식이 성립될 때 pq에 넣을 수 있다.

          current >= q.front().date
  • pq에 넣어진 것들은 supply가 가장 큰 순서대로 나열된다. 이는 밀가루를 greedy하게 골라 다른 날짜에서 밀가루를 또 받는 일을 방지한다.

      struct cmp{
          bool operator()(Data a, Data b){
              return a.supply < b.supply;
          }
      };
  • pq의 top에 있는 것이 공장이 받을 밀가루가 되므로, current += pq.top().supply;

코드

#include <bits/stdc++.h>
using namespace std;

struct Data{
    int date;
    int supply;
    Data(int a, int b): date(a), supply(b) {}
};

struct cmp{
    bool operator()(Data a, Data b){
        return a.supply < b.supply;
    }
};

int solution(int stock, vector<int> dates, vector<int> supplies, int k) {
    int answer = 0;
    int current = stock;

    priority_queue<Data, vector<Data>, cmp> pq;
    queue<Data> q;

    for(int i = 0; i < dates.size(); i++)
        q.push(Data(dates[i], supplies[i]));

    while(current < k){
        while(!q.empty() && current >= q.front().date){
            pq.push(q.front());
            q.pop();
        }

        current += pq.top().supply;
        pq.pop();
        answer++;
    }

    return answer;
}

채점 결과

프로그래머스 42626 - 더 맵게

문제 링크

생각 및 접근

  • 스코빌 지수가 제일 낮은 것과 그 다음으로 낮은 것을 찾아야 하므로 처음에는 C++ STL Algorithm의 sort로 해결하려고 했으나, 정렬하고 두 개 뽑아서 하나 넣고, 정렬하고 두 개 뽑아서 하나 넣고 식의 코드는 시간 효율이 너무 떨어질 것 같았다.
  • 그래서 새로 생각해낸 방식이 우선순위 큐 활용하기 (우선순위 큐에 대한 내용 링크)
  • 우선순위 큐를 최소 힙으로 선언하여, 우선순위 큐에 scoville의 값들을 다 넣고, 부모 노드 두개만 뽑아서 값을 체크하면 된다.
  • 답을 반환하는 시점
    • 우선순위 큐의 top이 K보다 크거나 같을 때 (모든 음식의 스코빌 지수를 K 이상으로 만든 경우)
    • 우선순위 큐의 top이 K보다 작고, 그 값이 우선순위 큐에 존재하는 유일한 원소일 때 (모든 음식의 스코빌 지수를 K 이상으로 만들 수 없는 경우)

코드

#include <bits/stdc++.h>
using namespace std;

int solution(vector<int> scoville, int K) {
    int answer = 0;

    priority_queue<int, vector<int>, greater<int> > pq;    
    for(auto s : scoville)  pq.push(s);

    while(-1){        
        int low1 = pq.top();
        pq.pop();
        if(low1 >= K)       return answer;
        if(pq.size() == 0)  return -1;

        int low2 = pq.top();
        pq.pop();

        pq.push(low1 + low2 * 2);
        answer++;
    }
}

채점 결과

프로그래머스 42842 - 카펫

문제 설명

생각 및 접근

사족

  • Leo의 눈썰미에 박수를 보낸다.

본문

  • yellow를 토대로 노란색의 카펫을 먼저 만들어본 뒤, 노란색의 카펫을 기준으로 갈색 카펫을 덧붙인다. 덧붙인 결과, brown과 갈색 카펫의 수가 같다면 정답이므로, 갈색 카펫의 크기를 반환하면 된다.
  • 노란색의 카펫을 만들기 위한 과정
    • 약수를 토대로 하였다.
  • 갈색 카펫을 덧붙인 뒤, 그 갯수를 세는 과정
    brown == (yellowWidth + 2) * 2 + (yellowHeight + 2) * 2 - 4

코드

#include <bits/stdc++.h>
using namespace std;

vector<int> solution(int brown, int yellow) {
    vector<int> answer;

    for(int i = 1; i <= yellow; i++){
        if(yellow % i == 0){
            int yellowWidth = max(i, yellow / i);
            int yellowHeight = min(i, yellow / i);

            if(brown ==  (yellowWidth + 2) * 2 + (yellowHeight + 2) * 2 - 4){
                answer.push_back(yellowWidth + 2);
                answer.push_back(yellowHeight + 2);
                break;
            }
        }
    }

    return answer;
}

채점 결과

+ Recent posts