https://programmers.co.kr/learn/courses/30/lessons/12916



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <string>
#include <iostream>
#include<algorithm>
using namespace std;
 
int cnt[2];
bool solution(string s)
{
    transform(s.begin(), s.end(), s.begin(), ::tolower);
    for (int i = 0; i < s.length(); i++) {
        if (s[i] == 'p') cnt[0]++;
        else if (s[i] == 'y') cnt[1]++;
    }
    if (cnt[0== cnt[1]) return 1;
    else return 0;
 
}
cs


https://www.welcomekakao.com/learn/courses/30/lessons/42577



해시 카테고리로 분류되어 있긴 하지만, 본인이 편한 풀이로 풀면 그만이다.



본인은 전화번호들을 길이가 길어지는 순서대로 정렬하였다.


이후에 짧은 전화번호를 기준으로 그것보다 긴 전화번호들을 비교했다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <string>
#include <vector>
#include<iostream>
#include<algorithm>
using namespace std;
 
bool cmp(string a, string b) {
    return a.length() < b.length();
}
bool solution(vector<string> pb) {
    sort(pb.begin(), pb.end(), cmp); //길이 짧은게 앞으로
    
    
 
    for (int i = 0; i < pb.size(); i++) {
        for (int j = i+1; j < pb.size(); j++) {
            bool isSame = true;
            for (int k = 0; k < pb[i].length(); k++) {
                if (pb[i][k] != pb[j][k]) {
                    isSame = false;
                    break;
                }
            }
            if (isSame) return false;
        }
    }
    return true;
}
 
int main(void) {
    solution({  "97674223""1195524421""119" });
    return 0;
}
 
 
cs


https://programmers.co.kr/learn/courses/30/lessons/17678


콘이 탈 수 있는 가장 늦은 셔틀버스를 타고 가려면, 몇시에 줄을 서야 하는지를 구하는 문제이다.


다음과 같은 방식으로 생각해 볼 수 있다.


기본적으로 가장 늦은 버스를 탄다는 것은, 막차를 탄다는 것이다. 따라서 막차에 자리가 있으면 그냥 막차를 타면 된다.


막차에 자리가 없는 경우를 생각해보면, 버스를 가장 늦은 시각에 탄 사람보다, 1분 더 빨리 나와서 버스를 타면 탈 수 있는 가장 마지막 순간에 버스를 타게 된다.


동일 시각이라도 콘은 가장 뒤에 줄을 선다고 했기 때문에, 1분 더 빨리 나와서 버스를 타면 되겠다.


위 두가지 경우로 구현을 해주면 되겠다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <string>
#include <vector>
#include<iostream>
#include<algorithm>
using namespace std;
 
struct Bus {
    int curPop, hour, mint; //버스 현재 인원, 출발 시, 출발 분
};
vector<Bus> bus;
 
string solution(int n, int t, int m, vector<string> timetable) {
    string answer = "";
    int hour = 9, minute = 0;
    for (int i = 0; i < n; i++) {
        bus.push_back({ 0, hour, minute });
        minute += t;
        if (minute >= 60) {
            hour++;
            minute -= 60;
        }
    }
    
    sort(timetable.begin(), timetable.end()); 
//일찍 온 사람부터 나오게 정렬(마지막에 탄사람이 제일 늦게 온 사람인데, 그 사람 찾으려고)
    
    int lastUp = 0// 마지막에 탄 사람의 인덱스
    for (int i = 0; i < timetable.size(); i++) {
        int hr = stoi(timetable[i].substr(02));
        int mn = stoi(timetable[i].substr(32));
        for (int j = 0; j < bus.size(); j++) {
            if (bus[j].curPop < m && (bus[j].hour > hr || (bus[j].hour == hr && bus[j].mint >= mn))) {
                bus[j].curPop++;
                lastUp = i;
                break//탈 버스가 정해졌으면 버스 검색 중지
            }
        }
    }
    string hrStr = "";
    string mnStr = "";
    if (bus[bus.size() - 1].curPop < m) { //막차에 자리가 남았다면 막차 시간에 오면 됨
         hrStr = to_string(bus[bus.size() - 1].hour);
         mnStr = to_string(bus[bus.size() - 1].mint);
 
    }
    else { //막차에 자리가 없으면, 마지막에 탄 사람보다 1분 일찍오면 무조건 탈 수 있음
        int lastHr = stoi(timetable[lastUp].substr(02));
        int lastMin = stoi(timetable[lastUp].substr(32));
        lastMin--;
        if (lastMin < 0) {
            lastHr--;
            lastMin += 60;
        }
         hrStr = to_string(lastHr);
         mnStr = to_string(lastMin);
    }
 
    if (hrStr.length() == 1) hrStr = '0' + hrStr;
    if (mnStr.length() == 1) mnStr = '0' + mnStr;
    answer = hrStr + ':' + mnStr;
    
    return answer;
}
cs


https://programmers.co.kr/learn/courses/30/lessons/17680


현재 캐시의 크기와, 사용 빈도에 관련된 정보를 배열을 활용해서 계속 검사해주며 miss와 hit 여부를 판단해주면 된다.


주의할 것은, 대소문자에 상관없이 비교를 하기 때문에 (Seoul과 seoul이 둘 다 입력으로 들어올 수 있는데, 같다고 판단해야 함) 이 부분을 잘 확인하면 된다.



어떤 문자열을 소문자로 변환하는 경우, algorithm 헤더에 있는 transform 함수를 이용한다.


파라미터는 transform(변환할 문자열의 시작주소, 변환할 문자열의 끝주소, 변환 결과를 저장할 문자열의 시작주소, ::변환방식)이다.


transform(ct[i].begin(), ct[i].end(), ct[i].begin(), ::tolower);


이런식으로 사용해준다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <string>
#include <vector>
#include<iostream>
#include<algorithm>
#include <string.h>
using namespace std;
int used[31], curSize = 0;
string cache[31];
int findCity(string city){
    for(int i = 0 ; i < curSize ; i++){
        if(cache[i] == city) return i;
    }
    return -1;
}
int solution(int sz, vector<string> ct) {
    int ans = 0;
    for(int i = 0 ; i < ct.size() ; i++){
        transform(ct[i].begin(), ct[i].end(), ct[i].begin(), ::tolower);
      
        int findIdx = findCity(ct[i]);
        if(findIdx >= 0){ //캐싱되어있는 경우
           ans++;
            for(int j = 0 ; j < curSize ; j++)
                used[j]++;
            used[findIdx] = 0;
        }
        else{
            //캐시 미스라서 추가해야 하는데 자리가 있는/없는 경우
            if(curSize < sz){ //자리 있
                cache[curSize] = ct[i];
                curSize++;
            }
            else// 자리 없
                int leastCnt = -1, idx = 0;
                for(int j = 0 ; j < curSize ; j++){
                    if(used[j] > leastCnt){
                        leastCnt = used[j];
                        idx = j;
                    }
                }
                cache[idx] = ct[i];
                 for(int j = 0 ; j < curSize ; j++){
                    if(j == idx) used[j] = 0;
                     else
                         used[j]++;
                }
            }
            ans += 5;
        }
    }
    return ans;
}
cs


https://programmers.co.kr/learn/courses/30/lessons/17682



문자열에서 숫자를 골라내야 하는데, 이 때 10이 포함된 경우를 잘 확인해주면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <string>
#include<iostream>
#include<vector>
using namespace std;
 
bool isNum(char a) {
    return 0 <= a - '0' && a - '0' <= 10;
}
int solution(string dr) {
    vector<int> numV;
    vector<char> boV, opV(3'!');
 
    int ans = 0;
 
    string strNum = "";
    for (int i = 0; i < dr.length(); i++) {
 
        if (isNum(dr[i])) strNum += dr[i];
        else {
            if (strNum != "") {
                numV.push_back(stoi(strNum));
                strNum = "";
            }
            if (dr[i] == 'S' || dr[i] == 'D' || dr[i] == 'T')
                boV.push_back(dr[i]);
            else if (dr[i] == '*' || dr[i] == '#')
                opV[boV.size() - 1= dr[i];
 
        }
    }
 
    for (int i = 0; i < 3; i++) {
        if (boV[i] == 'D') numV[i] *= numV[i];
        else if (boV[i] == 'T') numV[i] = numV[i] * numV[i] * numV[i];
 
        if (opV[i] == '*') {
            if (i == 0)
                numV[i] *= 2;
            else {
                numV[i] *= 2;
                numV[i - 1*= 2;
            }
        }
        else if (opV[i] == '#')
            numV[i] *= -1;
    }
 
    for (int i = 0; i < numV.size(); i++)
        ans += numV[i];
 
    return ans;
}
cs


https://programmers.co.kr/learn/courses/30/lessons/17681



비트연산 문제인데, 이진수로 변환한 뒤에 문자열 비교를 통해 풀었다. 0이 들어오는 경우 이진수로 변환할 때 조심해주면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include<iostream>
#include <string>
#include <vector>
using namespace std;
char map[17][17];
string decToBin(int dec, int n) {
    string bin = "";
    
    if (dec == 0) bin += "0";
    else {
        while (1) {
            if (dec == 0break;
            bin += to_string(dec % 2);
            dec /= 2;
        }
    }
    if (bin.length() < n) 
        for (int i = bin.length(); i < n; i++)
            bin += "0";
    
    string ret = "";
    for (int i = bin.length()-1; i >= 0; i--)
        ret += bin[i];
 
    return ret;
}
vector<string> solution(int n, vector<int> arr1, vector<int> arr2) {
    vector<string> answer;
    for (int i = 0; i < arr1.size(); i++) {
        string dec = decToBin(arr1[i], n);
        string dec2 = decToBin(arr2[i], n);
        for (int j = 0; j < n; j++) {
            if (dec[j] == '1') map[i][j] = '#';
            if (dec2[j] == '1') map[i][j] = '#';
        }
    }
 
    for (int i = 0; i < n; i++) {
        string ans = "";
        for (int j = 0; j < n; j++) {
            if (map[i][j] == '#') ans += '#';
            else
                ans += ' ';
         }
        answer.push_back(ans);
    }
    return answer;
}
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    solution(1, { 0 }, { 0 });
    return 0;
}
 
cs


https://www.welcomekakao.com/learn/courses/30/lessons/42891



정확성 테스트는, 그냥 조건대로 시뮬레이션을 돌리면 통과할 수 있지만, 효율성 테스트는 통과할 수 없다.


k의 범위가 매우 큰데, 나이브하게 풀면 k번 탐색해야하기 때문이다.



k번 탐색할 게 아니라, 최대로 음식의 개수만큼만 탐색하도록 구현할 수 있다.


음식을 먹는 데 소요되는 시간을 오름차순으로 정렬하고, 


(현 시점에서 가장 적은 시간이 소요되는 음식의 시간 * 남아있는 음식의 수)만큼의 시간을 한 번에 감소시킬 수 있다.


당연히 k도 갱신되어야 하고, 위에 계산한 시간이 k보다 작아야 가능하다.


저 시간이 k보다 크다면, 음식별 소요 시간으로 정렬해 두었던 것을, 다시 본래의 인덱스로 돌려준다. 이것 때문에 초반에 pair에 음식별 소요시간과 그 음식의 번호를 함께 저장하는 것이다.


이제는 나머지 연산을 활용해서, 먹어야할 음식을 찾아주면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <string>
#include <vector>
#include<iostream>
#include<algorithm>
 
using namespace std;
 
typedef pair<intint> pii;
typedef long long ll;
 
bool cmp(pii a, pii b) {
    return a.second < b.second;
}
int solution(vector<int> ft, long long k) {
    vector<pii> foods;
    for (int i = 0; i < ft.size(); i++
        foods.push_back({ ft[i], i + 1 }); //음식의 번호는 1부터
    
    sort(foods.begin(), foods.end());
    int remain = foods.size();
    ll spend, preTime = 0//spend = 현 시점에서 한번에 지울 수 있는 시간, pretime = 이전에 봤던 음식의 소요 시간
    for (vector<pii>::iterator itr = foods.begin(); itr != foods.end(); itr++, remain--) {
        spend = (itr->first-preTime) * remain;
        preTime = itr->first;
        if (spend == 0continue;
        else if (spend <= k) { //한번에 spend만큼 지울 수 있으면
            k -= spend;
        }
        else { //한번에 먹을 수 있는 양보다 k가 작으면
            sort(itr, foods.end(), cmp);//다시 음식들 원위치로 정렬
            k %= remain;
            return (itr + k)->second;
        }
    }
    return -1//먹을 수 있는 게 없어서, spend가 k보다 커진적 없이, 계속 0이라 스킵된 경우
}
int main(void) {
    vector<int> v;
    v = { 3,5,1,6,5,3 };
    int k = 20;
    solution(v, 20);
    return 0;
}
cs


https://www.welcomekakao.com/learn/courses/30/lessons/42892



순회는 간단한 부분이기 때문에, 사실 관건은 좌표를 이용해서 트리를 어떻게 만들 것이냐이다.


기본적으로 위에서부터, root를 시작으로 아래로 채워갈 것이기 때문에, 입력받는 좌표를 y값 내림차순으로 정렬한다. y좌표가 동일한 경우 x좌표 오름차순으로 정렬해서, 왼쪽 자식부터 확인할 수 있도록 한다.


정렬을 할 때, 아무런 처리를 해주지 않고 정렬하게 되면, 본인이 원래 몇 번째 인덱스였는지 잃어버리기 때문에, 이후에 순회를 할 수가 없다.


따라서 입력을 받을 당시에, 본인의 인덱스를(노드 번호) 갖고 있도록 처리를 해주어야 한다.



본인은 구조체를 이용했고, 사실 벡터에 그냥 인덱스를 추가해줘도 상관이 없을 것 같다.



트리를 만들 때는, 링크드리스트의 형태를 취해서 만드는 것도 가능하고, 배열의 인덱스를 루트로 해서 하는 방법도 가능하다.


본인은 후자로 구현했다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <string>
#include <vector>
#include<iostream>
#include<algorithm>
using namespace std;
 
struct Node {
    int idx, l = 0, r = 0, x, y;
}b[10001];
struct move {
    int l, r;
}m[10001];
bool cmp(Node a, Node b) {
    if (a.y > b.y) return true;
    else if (a.y < b.y) return false;
    else {
        return a.x < b.x;
    }
}
int num;
void makeTree(int root) {
 
    for (int i = 2; i <= num; i++) {
        int cur = root;
        while (1) {
            if (b[i].x < b[cur].x) {
                if (b[cur].l == 0) {
                    b[cur].l = i;
                    break;
                }
                else
                    cur = b[cur].l;
            }
            else {
                if (b[cur].r == 0) {
                    b[cur].r = i;
                    break;
                }
                else
                    cur = b[cur].r;
            }
        }
    }
}
vector<int> pre;
void preOrder(int cur) {
    if (cur == 0return;
    pre.push_back(cur);
    preOrder(m[cur].l);
    preOrder(m[cur].r);
}
vector<int> pos;
void postOrder(int cur) {
    if (cur == 0return;
    postOrder(m[cur].l);
    postOrder(m[cur].r);
    pos.push_back(cur);
}
vector<vector<int>> solution(vector<vector<int>> nodeinfo) {
    vector<vector<int>> answer;
    num = nodeinfo.size();
 
    for (int i = 1; i <= nodeinfo.size(); i++) {
        b[i].x = nodeinfo[i-1][0];
        b[i].y = nodeinfo[i-1][1];
        //cout << nodeinfo[i - 1][0] << ' ' << nodeinfo[i - 1][1] << '\n';
        b[i].idx = i;
    }
 
    sort(b+1, b + num+1, cmp); //1. y좌표 큰순, 2. x좌표 작은순
    
    makeTree(1); // root의 노드 번호
    
    for (int i = 1; i <= num; i++) {
        m[b[i].idx].l = b[b[i].l].idx;
        m[b[i].idx].r = b[b[i].r].idx;
    }
 
    preOrder(b[1].idx);
    postOrder(b[1].idx);
 
    answer.push_back(pre);
    answer.push_back(pos);
    return answer;
}
 
int main(void) {
    vector<vector<int>> nodeinfo;
    nodeinfo = { {5,3},{11,5}, {13,3}, {3,5}, {6,1}, {1,3}, {8,6}, {7,2}, {2,2} };
    solution(nodeinfo);
    return 0;
}
cs


https://www.welcomekakao.com/learn/courses/30/lessons/42889



stage k의 실패율은, 현재 stage k에 머물러 있는 사람/스테이지 k이상 시도한 사람


이라는 것을 이용했다. 두 배열을 만든 이후에, 부동 소수점 오차를 방지하기 위해서 나누는 연산은 하지 않고, 통분시 분자값을 비교해서 대소를 비교했다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <string>
#include <vector>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll cnt[502], d[502];
 
struct Info {
    ll idx, son = 0, mom = 0;
}info[502];
 
bool cmp(Info a, Info b) {
 
    if (a.son * b.mom > b.son * a.mom) return true;
    else if (a.son * b.mom == b.son * a.mom) {
        return a.idx < b.idx;
    }
    else
        return false;
}
vector<int> solution(int N, vector<int> stages) {
    vector<int> answer;
    
    for (int i = 0; i < stages.size(); i++) {
        cnt[stages[i]]++;
        for (int j = 1; j <= stages[i]; j++) {
            d[j]++;
        }
    }
    for (int i = 1; i <= N; i++) {
        info[i].idx = i;
        info[i].son = cnt[i];
        info[i].mom = d[i];
    }
    sort(info + 1, info + N+1, cmp);
 
    for (int i = 1; i <= N; i++)
        answer.push_back(info[i].idx);
    return answer;
}
cs


https://www.welcomekakao.com/learn/courses/30/lessons/42888



문제를 보면, ID와 닉네임을 대응해서 최신값으로 유지해야 한다. 기본적으로 사람이 입장하면 map에 추가를 해주면 되겠고, 닉네임을 변경하는 것이면, map에서 key값인 id에 대응되는 value인 닉네임을 업데이트 해주면 된다.


주의할 것은, 나가는 기능을 수행했을 경우, map에서 그 id의 데이터를 삭제하면 안 된다는 것이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include<vector>
#include<string>
#include<iostream>
#include<map>
using namespace std;
struct Rec {
    int cmd; //입장 0 퇴장 1 변경 2
    string id;
};
vector<Rec> rec;
map<stringstring> mp; //id, nick
 
vector<string> solution(vector<string> record) {
    vector<string> answer;
    for (int i = 0; i < record.size(); i++) {
        string cur = record[i];
        bool beenSpace = false;
        int firSpace, secSpace = 0, curCmd;
        if (cur[0== 'E') curCmd = 0//입장
        else if (cur[0== 'L') curCmd = 1//나감
        else if (cur[0== 'C') curCmd = 2//닉변
 
        for (int j = 0; j < cur.length(); j++) {
        
            if (cur[j] == ' ') {
                if (!beenSpace) {
                    beenSpace = true;
                    firSpace = j;
                }
                else secSpace = j;
            }
        }
        string curNick = cur.substr(secSpace + 1, cur.length() - secSpace - 1);
        
        string curId;
        if (curCmd == 0) { //입장
            curId = cur.substr(firSpace + 1, secSpace - firSpace - 1);
            mp[curId] = curNick;
        
            rec.push_back({ curCmd, curId });
        }
        else if (curCmd == 1) { //나감
            curId = cur.substr(firSpace + 1, cur.length() - firSpace - 1);
            rec.push_back({ curCmd, curId });
        }
        else { //닉변
            curId = cur.substr(firSpace + 1, secSpace - firSpace - 1);
            mp[curId] = curNick;
        }
    }
 
    for (int i = 0; i < rec.size(); i++) {
        string str = "";
        if (rec[i].cmd == 0) {
            str = mp[rec[i].id] + "님이 들어왔습니다.";
        }
        else if(rec[i].cmd == 1)
            str = mp[rec[i].id] + "님이 나갔습니다.";
        
        answer.push_back(str);
    }
    return answer;
}
cs


+ Recent posts