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

 

코딩테스트 연습 - 큰 수 만들기

 

programmers.co.kr

[풀이] Greedy

 

Upperbound를 이용해서 고를 수 있는 범위 내에서 9~0까지 for문을 돌면서 가장 먼저 선택할 수 있는

값을 하나씩 고르면 된다.

 

 

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
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
 
string solution(string number, int k) {
    string answer = "";
    vector<int> a[10];
    for (int j = 0; j < number.size(); j++) {
        a[number[j] - '0'].push_back(j);
    }
    
    int cur = -1;
    for (int i = k; i < number.size(); i++) {
        for (int j = 9; j >= 0; j--) {
            if (a[j].empty()) continue;
            if (answer == "" && j == 0continue;
            auto ub = upper_bound(a[j].begin(), a[j].end(), cur);
            if (ub == a[j].end()) continue;
 
            int m = ub - a[j].begin();
            if (a[j][m] <= i) {
                answer.push_back(j + '0');
                cur = a[j][m];
                break;
            }
        }
    }
    return answer;
}
cs

 

https://github.com/has2/Algorithm/blob/master/programmers/level2/%ED%81%B0%20%EC%88%98%20%EB%A7%8C%EB%93%A4%EA%B8%B0.cpp

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

 

코딩테스트 연습 - 조이스틱

조이스틱으로 알파벳 이름을 완성하세요. 맨 처음엔 A로만 이루어져 있습니다. ex) 완성해야 하는 이름이 세 글자면 AAA, 네 글자면 AAAA 조이스틱을 각 방향으로 움직이면 아래와 같습니다. ▲ - 다

programmers.co.kr

[풀이] Greedy

 

가장 효율적으로 알파벳을 변경하는 방법은 이동시 가장 가까운 곳으로 이동해서 변경해주는 것이다.

어차피 변경해야할 모든 알파벳을 방문해야 하기 때문이다.

 

어떤 알파벳을 방문할 때 <-,->를 이용하는 두가지 방법 중 min값이 이동거리이다.

 

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
#include <string>
#include <vector>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int solution(string name) {
    int answer = 0;
 
    string curName(name.size(), 'A');
    int cur = 0;
 
    while (name != curName) {
 
        int near = -1;
        int minDiff = 30;
        for (int i = 0; i < name.size(); i++) {
            if (name[i] != curName[i]) {
                int diff = abs(cur - i);
                diff = min(diff, (int)name.size() - diff);
                if (minDiff > diff) {
                    near = i;
                    minDiff = diff;
                }
            }
        }
        cur = near;
        curName[cur] = name[cur];
        answer += minDiff;
        
        int k = name[cur] - 'A';
        answer += min(26 - k, k);
 
        //cout << "cur : " << cur << ", minDiff : " << minDiff << ", k : " << k << ", len -k : " << 26-k << endl;
    }
 
    return answer;
}
cs
https://github.com/has2/Algorithm/blob/master/programmers/level2/%EC%A1%B0%EC%9D%B4%EC%8A%A4%ED%8B%B1.cpp

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

 

코딩테스트 연습 - 더 맵게

매운 것을 좋아하는 Leo는 모든 음식의 스코빌 지수를 K 이상으로 만들고 싶습니다. 모든 음식의 스코빌 지수를 K 이상으로 만들기 위해 Leo는 스코빌 지수가 가장 낮은 두 개의 음식을 아래와 같��

programmers.co.kr

[풀이] 우선순위 queue

 

시간복잡도 : O(nlgn)

 

 

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
#include <cstdio>
#include <queue>
#include <vector>
 
using namespace std;
 
int solution(vector<int> scoville, int K) {
    int answer = 0;
 
    priority_queue<int> pq;
    for (int& t : scoville) pq.push(-t);
    
    while (!pq.empty()) {
 
        if (-pq.top() >= K) return answer;
        if (pq.size() <= 1return -1;
 
        int a = -pq.top(); pq.pop();
        a += -2 * pq.top(); pq.pop();
 
        pq.push(-a);
 
        answer++;
    }
    return answer;
}
cs
https://github.com/has2/Algorithm/blob/master/programmers/level2/%EB%8D%94%20%EB%A7%B5%EA%B2%8C.cpp

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

 

코딩테스트 연습 - 괄호 변환

카카오에 신입 개발자로 입사한 콘은 선배 개발자로부터 개발역량 강화를 위해 다른 개발자가 작성한 소스 코드를 분석하여 문제점을 발견하고 수정하라는 업무 과제를 받았습니다. 소스를 컴�

programmers.co.kr

[풀이] 재귀,구현,Stack

 

문제에 써있는 대로 구현하면 된다.

1. 균형잡힌 괄호 문자열 찾기 int getBalance(string& s)

  여는 괄호와 닫는 괄호의 갯수가 같아지는 순간의 index를 반환

 

2. 올바른 문자열 체크 bool isRight(string& s)

  stack을 이용하였다. 여는 괄호의 경우 무조건 push, 닫는 괄호인 경우에

  stack이 비어있으면 올바른 괄호 문자열이 아니므로 false 리턴

  

위의 두 함수를 이용해서 재귀적으로 solution 함수를 채워주면 된다.

 

#include <string>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
string p = "()";
int getBalance(string& s) {
	int ret = 0;
	int l=0, r=0;
	for (int i = 0; i < s.size(); i++) {
		if (s[i] == '(') l++;
		else r++;
		if (l == r) {
			ret = i+1;
			break;
		}
	}
	return ret;
}

bool isRight(string& s) {
	stack<int> st;

	for (int i = 0; i < s.size(); i++) {
		char c = s[i];
		if (c == '(') {
			st.push(c);
		}
		else {
			if (st.empty()) {
				return false;
			}
			else {
				st.pop();
			}
		}

	}
	return true;
}
string rev(string& s) {
	string ret = "";
	for (int i = 1;i<s.size()-1;i++) {
		ret.push_back(s[i] == ')' ? '(' : ')');
	}
	return ret;
}

string solution(string p) {
	
	if (p == "") return p;
	string ret;

	int sz = getBalance(p);
	string w = p.substr(0, sz);
	string u = p.substr(sz, p.size() - sz);

	string k = solution(u);
	if (isRight(w)) {
		ret = w + k;
	}
	else {
		ret = "("+k+")";
		ret += rev(w);
	}
	return ret;
}

https://github.com/has2/Algorithm/blob/master/programmers/level2/%EA%B4%84%ED%98%B8%20%EB%B3%80%ED%99%98.cpp

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

 

코딩테스트 연습 - 카카오프렌즈 컬러링북

6 4 [[1, 1, 1, 0], [1, 2, 2, 0], [1, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 3], [0, 0, 0, 3]] [4, 5]

programmers.co.kr

[풀이]

DFS

#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
int dy[4] = { 1,-1,0,0 };
int dx[4] = { 0,0,1,-1 };
int M, N;
bool visit[101][101];

int dfs(vector<vector<int>>& picture, int y, int x) {
	
	visit[y][x] = 1;

	int ret = 1;
	for (int i = 0; i < 4; i++) {
		int ty = y + dy[i];
		int tx = x + dx[i];
		
		if (ty < 0 || tx < 0 || ty >= M || tx >= N || visit[ty][tx]
			|| picture[ty][tx] != picture[y][x]) continue;

		ret += dfs(picture, ty, tx);
	}
	return ret;
}

vector<int> solution(int m, int n, vector<vector<int>> picture) {
	int number_of_area = 0;
	int max_size_of_one_area = 0;
	M = picture.size();
	N = picture[0].size();

	memset(visit, 0, sizeof(visit));

	for (int i = 0; i < M; i++) {
		for (int j = 0; j < N; j++) {
			if (picture[i][j] == 0 || visit[i][j]) continue;
			number_of_area++;
			max_size_of_one_area = max(max_size_of_one_area, dfs(picture, i, j));
		}
	}


	vector<int> answer(2);
	answer[0] = number_of_area;
	answer[1] = max_size_of_one_area;
	return answer;
}

https://github.com/has2/Algorithm/blob/master/programmers/level2/%EC%B9%B4%EC%B9%B4%EC%98%A4%20%ED%94%84%EB%A0%8C%EC%A6%88%20%EC%BB%AC%EB%9F%AC%EB%A7%81%EB%B6%81.cpp

문제링크 : https://programmers.co.kr/learn/courses/30/lessons/60057

 

코딩테스트 연습 - 문자열 압축

데이터 처리 전문가가 되고 싶은 어피치는 문자열을 압축하는 방법에 대해 공부를 하고 있습니다. 최근에 대량의 데이터 처리를 위한 간단한 비손실 압축 방법에 대해 공부를 하고 있는데, 문자

programmers.co.kr

[풀이과정]

1. 문자열 길이가 n인 경우 1~n/2으로 잘랐을 경우를 모두 구한다. (n/2를 넘게 자르는 것은 불가능)

 

2. 길이 len으로 자른 경우 길이가 len인 substring을 한개씩 비교하면서 앞의 것과 같으면 압축 가능한 개수를 저장하는 cnt를 1 더해준다.

 

3. 다른 문자열이 나오면 cnt의 길이 + len만큼을 ret에 더해준다.

 (cnt를 string으로 변환 후 size 구함, cnt가 1인 경우 더해주지 않음)

 

4. 다음 index (i+len)이 s의 길이를 초과하는 경우 더 이상 압축이 불가능 하므로 남아있는 것을 더해준다.

   (s2.size()만큼 더해주는 이유는 제일 마지막 부분 문자열은 len보다 작을수도 있기 때문에)

 

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

int sol(string& s, int len) {

	int ret = 0;

	int cnt = 1;
	for (int i = len; i < s.size() ; i += len) {
		string s1 = s.substr(i-len, len);
		string s2 = s.substr(i, len);
		//cout << s1 << "," << s2 << endl;
		if (s1 == s2) {
			cnt++;
		}
		else {
			ret += len;
			if (cnt != 1) ret += to_string(cnt).size();
			cnt = 1;
		}
		if (i + len >= s.size()) {
			ret += s2.size();
			if (cnt != 1) ret += to_string(cnt).size();
		}
		//cout << ret << endl;

	}
	return ret;
}

int solution(string s) {
	if (s.size() == 1) return 1;

	int answer = 10000;

	for (int i = 1; i <= s.size() / 2; i++) {
		answer = min(answer,sol(s, i));
	}

	return answer;
}

https://github.com/has2/Algorithm/blob/master/programmers/level2/%EB%AC%B8%EC%9E%90%EC%97%B4%20%EC%95%95%EC%B6%95.cpp

문제링크 : https://programmers.co.kr/learn/courses/30/lessons/42583

 

코딩테스트 연습 - 다리를 지나는 트럭

트럭 여러 대가 강을 가로지르는 일 차선 다리를 정해진 순으로 건너려 합니다. 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 알아내야 합니다. 트럭은 1초에 1만큼 움직이며, 다리 길이��

programmers.co.kr

#include <string>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

int solution(int bridge_length, int weight, vector<int> truck_weights) {
	int answer = 0;
	queue<pair<int,int>> q;

	int cnt = truck_weights.size();
	int cur_i = 0;
	int cur_w = 0;
	int time = 0;

	while (1) {

		if (cur_i < cnt && cur_w + truck_weights[cur_i] <= weight) {

			int qsize = q.size();
			while (qsize--) {

				auto truck = q.front();
				q.pop();
				if (truck.second != bridge_length) {
					q.push(make_pair(truck.first, truck.second + 1));
				}
				else {
					cur_w -= truck_weights[truck.first];
				}
			}
			
			cur_w += truck_weights[cur_i];
			q.push(make_pair(cur_i++, 1));
			time++;
		}
		else if (!q.empty()) {

			auto truck = q.front();
			q.pop();

			cur_w -= truck_weights[truck.first];

			int offset = bridge_length - truck.second+1;
			int qsize = q.size();
			while (qsize--) {
				truck = q.front();
				q.pop();
				q.push(make_pair(truck.first, truck.second + offset));
			}

			if (cur_i < cnt && cur_w + truck_weights[cur_i] <= weight) {
				cur_w += truck_weights[cur_i];
				q.push(make_pair(cur_i++, 1));
			}

			time += offset;
		}
		else {
			answer = time;
			break;
		}
		//printf("time : %d\n", time);
	}
	
	return answer;
}

int main() {

	int bridge = 2;
	int wi = 10;
	vector<int> a = { 7,4,5,6 };

	//int bridge = 100;
	//int wi = 100;
	//vector<int> a = { 10 };

	//int bridge = 1;
	//int wi = 6;
	//vector<int> a = { 6,6};

	printf("%d", solution(bridge, wi, a));

}

소스코드 : https://github.com/has2/Algorithm/blob/master/programmers/level2/%EB%A9%80%EC%A9%A1%ED%95%9C%20%EC%82%AC%EA%B0%81%ED%98%95.cpp

 

+ Recent posts