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://www.acmicpc.net/problem/11328

 

11328번: Strfry

문제 C 언어 프로그래밍에서 문자열(string)은 native한 자료형이 아니다. 사실, 문자열은 그저, 문자열의 끝을 표시하기 위한 말단의 NULL이 사용된, 문자들로 이루어진 문자열일 뿐이다. 하지만 프로그래밍 언어에서 문자열을 다루는 것은 매우 중요하기 때문에, C 표준 라이브러리는 문자열을 다루는 데에 매우 유용한 함수들을 제공하고 있다 : 그들 중에는 strcpy, strcmp, strtol, strtok, strlen, strcat 가 있다.

www.acmicpc.net

 

문자열을 무작위 재배열해서 반환하는 함수에 대한 문제이다.

두 문자열의 알파벳 성분이 일치하면 되기 때문에, 각 문자열을 이루는 알파벳의 개수를 파악해주면되겠다.

 

입력은 소문자로만 들어온다는 것을 확인하고, 각 문자열의 알파벳 개수를 파악해주자.

 

 

#include<string>
#include<iostream>
using namespace std;
int alpSrc[26], alpDes[26];
int main(void) {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int tc;
	cin >> tc;
	string src, des;
	bool res = true;
	while (tc--) {
		
		cin >> src >> des;
		for (int i = 0; i < src.length(); i++) {
			alpSrc[src[i] - 'a']++;
			alpDes[des[i] - 'a']++;
		}
		res = true;
		for (int i = 0; i < 26; i++) {
			if (alpSrc[i] != alpDes[i]) {
				res = false;
				break;
			}
		}
		if (res)
			cout << "Possible" << '\n';
		else
			cout << "Impossible" << '\n';

		for (int i = 0; i < 26; i++) {
			alpSrc[i] = 0;
			alpDes[i] = 0;
		}
	}
	return 0;


https://www.acmicpc.net/problem/16637



중요한 부분은


1. 수식의 길이를 n이라고 했을 때, 넣을 수 있는 괄호의 최대 개수 찾기


2. 수식을 계산하기


두 가지로 나눌 수 있다.



괄호의 최대 개수는 몇 개의 예시를 통해서 규칙을 찾을 수 있다.


계산을 할 때에는, 계산에 필요한 연산자와 피연산자를 구분해서 벡터에 저장해둔 이후에, 계산을 하게 되면, 연산자의 개수는 항상 피연산자의 개수보다 하나 적다는 것을 이용해서 깔끔하게 계산할 수 있다.



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
93
94
95
96
97
98
99
100
#include<iostream>
#include<string>
#include<limits.h>
#include<vector>
 
using namespace std;
typedef long long ll;
int n, maxBrac, arr[20], st = 1, num[20];
vector<ll> numV; //피연산자
vector<char> oprV; //연산자
 
char opr[20];
string cmd;
bool isused[20], picked[20], done[20];
int ans = -1 * INT_MAX;
 
void init() {
    for (int i = 0; i < n; i++) {
        picked[i] = false;
        done[i] = false;
    }
}
ll cal(int a, char op, int b) { //계산 과정에서 int 범위를 벗어날 수 있다
    if (op == '+')
        return (ll)(a + b);
    else if (op == '*')
        return (ll)(a*b);
    else if (op == '-')
        return (ll)(a - b);
}
void btk(int k, int maxBr) {
    if (k == maxBr) {
        for (int i = 0; i < maxBr; i++) {
        
            picked[arr[i]-1= true;
            picked[arr[i]] = true;
            picked[arr[i]+1= true;
        }
        
        for (int i = 0; i < n; i++) { //괄호로 묶인 값들 계산하면서 연산자, 피연산자 벡터에 삽입
            if (!picked[i]) {
                if (num[i] != -1)
                    numV.push_back(num[i]);
                else
                    oprV.push_back(opr[i]);
            }
            else if(picked[i]){
                if (done[i]) continue;
                else {
                    numV.push_back(cal(num[i], opr[i + 1], num[i + 2]));
                    done[i] = true;
                    done[i + 1= true;
                    done[i + 2= true;
                }
            }
        }
 
        ll res = numV[0]; //수식 계산
        for (int i = 1; i < numV.size(); i++) {
            res = cal(res, oprV[i - 1], numV[i]);
        }
    
        if (ans < res) ans = res;
        init();
        oprV.clear();
        numV.clear();
        return;
    }
    if (k == 0) st = 1;
    for (int i = st; i < n; i += 2) {
        if (!isused[i]) {
            arr[k] = i;
            st = i;
            isused[i] = true;
            isused[i + 2= true//연산자를 선택하면, 바로 인접한 연산자는 고를 수 없음
            btk(k + 1, maxBr);
            isused[i + 2= false;
            isused[i] = false;
        }
    }
}
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> cmd;
 
    maxBrac = (n + 1/ 4//수식의 길이가 n일 때, 넣을 수 있는 괄호의 최대 개수
    for (int i = 0; i < cmd.length(); i++) {
        if (i % 2 == 0) num[i] = cmd[i]-'0'//입력은 문자로 들어온다
        else {
            opr[i] = cmd[i];
            num[i] = -1//입력이 음수가 들어오는 경우는 없으므로 -1로 초기화
        }
    }
    for(int i = 0 ; i <= maxBrac ; i++)
        btk(0, i);
    cout << ans;
    return 0;
}
 
cs


https://www.acmicpc.net/problem/16637


백준 16637번 괄호 추가하기라는 문제인데, 이 문제를 풀면서 했던 뻘짓을 기록해두려고 한다.


3+8*2 이런 문자열이 있다고 할 때, 결과값을 내도록 구현하려면 어떻게 해야할까?


그냥 str[0] ~ str끝까지 한 문자 한 문자 확인하려고 생각하는 순간 굉장히 피곤해진다.


324 + 232 이런 경우처럼, 한 자리수가 아닌 숫자가 존재할 수 있기 때문이다. 처음에 이렇게 접근했다가, 결과적으로 아래와 같은 뻘짓을 하게 되었다.


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
string calculate(int a, char opt, int b) {
 
    if (opt == '+'return to_string(a + b);
 
    else if (opt == '-'return to_string(a - b);
    else
        return to_string((ll)(a*b));
}
int makeAns(string cur) {
    if (cur.length() == 0return 0;
    int res = stoi(cur.substr(01));
    for (int i = 1; i < cur.length() - 1; i++) {
        if (cur[i] - '0' < INT_MAX && cur[i] - '0' > -1 * INT_MAX) continue;
        if (!(cur[i] - '0' < INT_MAX && cur[i] - '0' > -1 * INT_MAX)) {
            if (cur[i + 1- '0' < INT_MAX && cur[i + 1- '0' > -1 * INT_MAX) {
                res += stoi(calculate(res, cur[i], stoi(cur.substr(i + 11))));
            }
            else {
                i++;
                res += stoi(calculate(res, cur[i], -1 * stoi(cur.substr(i + 21))));
            }
        }
    }
    cout << "계산결과 : " << res << '\n';
}
void process() {
    string str = "";
    for (int i = 0; i < n; i++) {
        if (!picked[i]) str += cmd[i];
        else {
            if (done[i]) continue;
            else {
                int a, b;
                a = stoi(cmd.substr(i, 1));
                b = stoi(cmd.substr(i + 21));
                str += calculate(a, cmd[i + 1], b);
                done[i] = true;
                done[i + 1= true;
                done[i + 2= true;
            }
        }
    }
    cout << str << '\n';
 
 
}
cs



위와 같은 뻘짓을 하지 않으려면, 연산자와 피연산자를 분리해서 벡터(배열)에 저장하고 있으면 된다. 연산하기가 훨씬 수월하다.


1
2
3
4
ll res = numV[0];
        for (int i = 1; i < numV.size(); i++) {
            res = cal(res, oprV[i - 1], numV[i]);
        }
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


https://www.acmicpc.net/problem/2661



1,2,3 세개의 숫자를 활용해서 길이 n의 수열을 만들면 된다.


기본적으로 여기까지는 백트래킹을 활용해서 진행해주면 된다.


이후에 나쁜 수열을 걸러내는 과정에서 substr을 적절히 활용해주면 되겠다.


주의할 점은, 검사를 재귀의 진입 부분에서 해야 한다는 것이다.



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
#include<iostream>
#include<set>
#include<string>
using namespace std;
int n, a[3= { 1,2,3 }, arr[81];
string str = "";
set<string> ans;
bool ef = false;
void backTracking(int k) {
 
    str = "";
    for (int i = 0; i < k; i++)
        str += (arr[i] + '0');
    
    //부분 수열 존재 검사
    for (int i = 1; i <= k / 2; i++) { //수열 길이 절반까지만 확인하면 됨
        for (int j = 0; j <= k - 2 * i; j++) {
            if (str.substr(j, i) == str.substr(j + i, i)) {
                return;
            }
        }
    }
 
    //길이 n 완성
    if (k == n) {
        for (int i = 0; i < k; i++)
            cout << arr[i];
        exit(0); //가장 먼저 나오는 게 제일 작은 수열
        return;
    }
 
    for (int i = 0; i < 3; i++) {
        arr[k] = a[i];
        backTracking(k + 1);
        if (ef) return;
    }
}
 
int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n;
    backTracking(0);
 
    return 0;
}
cs


+ Recent posts