Problem Solving/Programmers
Programmers [2020 카카오 인턴십]: 보석 쇼핑 풀이 및 코드
이진2
2020. 8. 29. 16:51
https://programmers.co.kr/learn/courses/30/lessons/67258
코딩테스트 연습 - 보석 쇼핑
["DIA", "RUBY", "RUBY", "DIA", "DIA", "EMERALD", "SAPPHIRE", "DIA"] [3, 7]
programmers.co.kr
아래와 같이 진열된 보석 진열대에서 각 종류의 보석을 1개 이상 포함하는 가장 짧은 구간을 찾아내는 것
문제의 설명을 보고 DP인가? 라고 생각했는데 DP의 접근방식과 유사하지만 다르게 풀이했다
이러한 경우에서는 번호 3~7번까지의 구간이 R, D, D, E, S의 모든 종류를 포함하면서 가장 짧은 구간이다😉
1. 보석 이름은 string 형식으로 되어있기 때문에 stl map을 만들어 각각의 보석을 번호에 매핑한다
2. 진열대 번호 개수만큼 아래의 과정을 반복한ㄷㅏ
3. start(초기 0)을 하나씩 늘려가면서 start ~ cur 구간이 보석 종류를 유지하는지 체크한다
4. 구간 안의 보석 종류가 줄어들지 않을 때 까지 start를 늘린다
5. 만약 구간 안에 모든 보석 종류가 있다면 구간 최소값을 갱신한다
6. cur를 +1하고 3번으로 돌아간다
#include <string>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
typedef struct {
int s, f, d;
}str;
bool cmp(str a, str b) {
if (a.d == b.d)return a.s < b.s;
return a.d < b.d;
}
vector<int> solution(vector<string> gems) {
vector<int> answer;
vector<int> v;
map<string, int> m;
int count = 1;
for (int i = 0; i < gems.size(); i++) {
map<string, int>::iterator it;
it=m.find(gems[i]);
if (it == m.end()) {
m[gems[i]] = count;
v.push_back(count);
count++;
}
else
v.push_back(m[gems[i]]);
}
int start = 0;
vector<int> check(count);
vector<str> ans;
for (int cur = 0; cur < gems.size(); cur++) {
check[v[cur]]++;
vector<int> tmp = check;
while (start < cur) {
tmp[v[start]]--;
int i = 1;
for(;i<tmp.size();i++)
if (check[i]!=tmp[i]&&!tmp[i])break;
if (i == tmp.size()) {
check = tmp;
start++;
}
else break;
}
bool b = 1;
for (int i = 1; i < check.size(); i++)
if (!check[i])b = 0;
if (b)
ans.push_back({ start,cur,cur-start+1 });
}
sort(ans.begin(), ans.end(), cmp);
answer.push_back(ans[0].s+1);
answer.push_back(ans[0].f+1);
return answer;
}
시간복잡도:
gems배열의 크기를 N이라 할 때,
보석 종류가 모두 같아도, 모두 달라도 시간복잡도는 O(N)이다.
아마 보석 종류가 루트N 정도일 때 가장 클 듯 . . . ?🤔