공부/Code Cata

롤케이크 자르기

동그래님 2025. 4. 1. 09:51

https://school.programmers.co.kr/learn/courses/30/lessons/132265

문제의 제한사항을 확인하고 브루트포스 기법으로는 해결할 수 없다는 생각이 들었다.
그래서 루프를 돌면서 현재 인덱스를 기준으로 왼쪽과 오른쪽을 나눠 set에 저장한 뒤, 두 개의 set 크기가 같다면 answer의 값을 증가 시켜주는 방향으로 문제를 해결하려했다.

✅ 초기 작성 코드

#include <string>
#include <vector>
#include <unordered_set>

using namespace std;

int solution(vector<int> topping) 
{
    int answer = 0;
    for(int i = 0; i < topping.size(); ++i)
    {
        unordered_set<int> left(topping.begin(), topping.begin() + i + 1);
        unordered_set<int> right(topping.begin() + i + 1, topping.end());
        
        if(left.size() == right.size()) answer++;
    }
    
    return answer;
}
하지만 시간초과로 오답 처리가 되었다..
이유는 매 반복문 안에서 set을 범위 기반으로 초기화 하는 과정에서, 루프가 또 돌기 때문에 시간 복잡도 비용이 크게 증가하였던 것이다.
그래서 매 루프마다 set을 초기화 하는 것이 아니라, 미리 right에 모든 topping의 개수를 저장한 뒤, 전체 루프를 돌며 현재 인덱스 값을 left로 하나씩 옮겨가며 양쪽의 토핑 개수가 같은지 체크하는 방향으로 수정이 필요했다.

 

✅ 수정 코드

#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>

using namespace std;

int solution(vector<int> topping)
{
    int answer = 0;
    unordered_set<int> left;
    unordered_map<int, int> right;
    for (int t : topping)
    {
        right[t]++;
    }

    for (int t : topping)
    {
        right[t]--;
        left.insert(t);

        if (right[t] <= 0) right.erase(t);
        if (left.size() == right.size()) answer++;
    }

    return answer;
}
초기 모든 topping을 set에 넣는다면, 중복되어 존재하는 토핑을 확인할 수 없어 unordered_map으로 right를 선언하였고, left는 중복과 상관 없이, 토핑이 있는지 없는지만 판단하면 되기에 그대로 unodered_set으로 선언해주었다.

topping 전체를 순회하며 각 토핑이 몇 개 있는지 정리해서 right에 넣어주었고, 이후 다시 전체 루프를 돌며 right에선 현재 인덱스 토핑을 빼주고, left에 넣어주었다.
만약 right에 인덱스 토핑 개수가 0이라면, 해당 키 값을 삭제했고 left와 right의 개수가 같다면 answer의 값을 증가시켜주며 값을 도출했다.