-
프로그래머스 - 보석 쇼핑 [C++]문제 풀이/프로그래머스 2023. 9. 7. 12:04반응형
이 문제는 투 포인터와 맵을 이용해서 풀었다. gems 배열의 최대 크기가 100,000 이므로 O(n) 시간 이내의 알고리즘을 구상해야 한다. 구간에 대한 정답을 도출해야 하므로 투 포인터를 떠올렸고, 개수에 상관없이 종류가 모두 들어가야하므로 맵을 떠올렸다.
일단 투 포인터를 사용하는 방식에는 한쪽에서 모두 시작하는 것과 양쪽에서 서로 시작하는 것이 있는데, 최소 구간이 같을 경우 시작 진열대 번호가 같아야하므로 왼쪽에서 모두 시작하는 쪽이 더 직관적이라고 생각했다. 처음에는 구간을 찾고 모든 보석의 종류가 들어있는지를 확인하기 위해 mp을 순회하면서 개수를 세는 쪽으로 하려 했으나, 이 방식은 시간 초과가 날 것이다. 만약 입력 배열이 10만이고 각 원소가 모두 다른 보석이라면, 10만 * 10만의 연산을 하기 때문이다.
그래서 두번째 방식으로 mp의 size를 통해 계산하는 방법을 생각했다. 이를 위해서는 left가 옮겨갈 때 mp의 카운트가 0이 되면 그 요소를 맵에서 제거해줘야 한다. 맵의 find 연산과 erase 연산이 O(log n) 시간만 되어준다면 시간 초과가 나지 않을 것이라 생각했고, 실제로 시간 초과가 나지 않고 정답을 도출할 수 있었다.
#include <string> #include <vector> #include <map> #include <algorithm> using namespace std; vector<int> solution(vector<string> gems) { vector<int> answer; map<string, int> tempCnt; for (string& gem : gems) { tempCnt[gem]++; } int allSize = tempCnt.size(); int size = gems.size(); map<string, int> mp; int left = 0; int right = 0; mp[gems[left]]++; int answerLeft = 0; int answerRight = size; while (left <= right && right < size) { if (allSize == mp.size()) { // 만족하는 경우 int range = right - left + 1; if (range < answerRight - answerLeft + 1) { answerLeft = left; answerRight = right; } else if (range == answerRight - answerLeft + 1) { answerLeft = min(answerLeft, left); answerRight = min(answerRight, right); } mp[gems[left]]--; if (mp[gems[left]] == 0) { auto it = mp.find(gems[left]); mp.erase(it); } left++; continue; } // 만족하지 않는 경우 right++; if (right < size) { mp[gems[right]]++; } } answer.push_back(answerLeft + 1); answer.push_back(answerRight + 1); return answer; }
반응형'문제 풀이 > 프로그래머스' 카테고리의 다른 글
프로그래머스 - 자물쇠와 열쇠 [C++] (0) 2023.09.08 프로그래머스 - 풍선 터트리기 [C++] (0) 2023.09.07 프로그래머스 - 메뉴 리뉴얼 [C++] (0) 2023.09.06 프로그래머스 - 두 큐 합 같게 만들기 [C++] (0) 2023.09.05 프로그래머스 - 삼각 달팽이 [C++] (0) 2023.09.04