알고리즘

보석 쇼핑 [카카오 2020 인턴 코딩테스트] C++ 투포인터 간단 명확 풀이

sunggook lee 2020. 9. 6. 00:35

전형적인 투포인터 문제이다.

 

 

 

다음과 같이

for(int i=0;i<gems.size();i++)
    s.insert(gems[i]);

 

set을 이용해 중복되지않은 보석의 개수를 구했고

 

while문을 돌며 투포인터 lo , hi를 증가시켜가며 Map에다 현재 start와 end를 저장했다.

 

 

- map으로 투포인터의 범위를 저장한 이유 

 

처음엔 map대신 set을 사용했으나 투포인터에서 지나간 범위는 삭제를 해줘야하는데

 

만약 set으로 해놓고 DIA를 지워버리면 범위내에 또 DIA가 있다면 지워지지 않아야할 원소도 지우기 때문이다.

 

따라서 Map을 사용하여 (Map <String,int>) 보석의 이름과 그 보석이 마지막으로 위치했던 인덱스를 저장해놓는다.

 

이렇게 저장해놓는다면 DIA가 0과 3 두군데에 있엇다면 0에있는 DIA를 지나갈때는 지우지 않고 3에있는 DIA를 지나갈때만 Map에서 삭제한다.

 

if(m[gems[lo]]==lo)
  m.erase(gems[lo]); 

 

다음 그림과 같이, Map 사이즈가 Set사이즈와 동일해 진다면 정답범위를 나타내는 벡터 v에 저장하고

Map에서 삭제해야 하는 보석이면 삭제하고 lo를 증가시켜 투포인터를 계속 순회한다.

	if(m.size()==s.size())
        {
            v.push_back(make_pair(lo,hi-1));
            
            if(m[gems[lo]]==lo)
                m.erase(gems[lo]);  
            lo++;
            
            if(hi>gems.size()) break;
        }

 

 

배열의 범위가 최대 10만 이므로 브루트 포스방식으로 푼다면 O(n^2)이 된다. 이는 정확성 풀이에서는 다 맞출 수 있지만

 

효율성 풀이에서 통과할 수 없다. 따라서 투포인터 방식으로 다음과 같이 풀어야 한다.

 

 

 

정답 코드 

 

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

bool comp(pair <int,int> a,pair <int,int> b)
{
    if(a.second-a.first == b.second-b.first)
        return a.first<b.first;
    return a.second-a.first < b.second-b.first;
}

vector<int> solution(vector<string> gems) {
    vector<int> answer;
    
    set <string> s;
    map <string,int> m;
    
    for(int i=0;i<gems.size();i++)
    s.insert(gems[i]);
    
    vector <pair <int,int> > v;
    int lo=0; int hi=0;
    
    while(true)
    {
        if(m.size()==s.size())
        {
            v.push_back(make_pair(lo,hi-1));
            
            if(m[gems[lo]]==lo)
                m.erase(gems[lo]);  
            lo++;
            
            if(hi>gems.size()) break;
        }
        else
        {
            if(hi>=gems.size()) break;
            
            m[gems[hi]]=hi;
            hi++;
        }
        
        
    }
    
    sort(v.begin(),v.end(),comp);
    answer.push_back(v[0].first+1);
    answer.push_back(v[0].second+1);
    return answer;
}