https://github.com/NMEii/Algorithms/tree/main/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/1/140108.%E2%80%85%EB%AC%B8%EC%9E%90%EC%97%B4%E2%80%85%EB%82%98%EB%88%84%EA%B8%B0

 

Algorithms/프로그래머스/1/140108. 문자열 나누기 at main · NMEii/Algorithms

This is an auto push repository for Baekjoon Online Judge created with [BaekjoonHub](https://github.com/BaekjoonHub/BaekjoonHub). - NMEii/Algorithms

github.com

 

설계

첫번째 문자를 x로 선언하고 문자열을 순회 하면서 n번째 문자가 x와 같으면 sameCount++, 다르면 diffCount++ 을 진행하고 각 카운트의 크기가 같다면 문자열을 자르고 answer++ 진행 하고 그뒤를 진행한다.

 

구현

#include <string>
#include <vector>

using namespace std;

int solution(string s) {
    int answer = 0;

    vector<string> save;

    char x = s[0];
    int sameCount = 0;
    int diffCount = 0;

    for (int i = 0; i < s.length(); i++)
    {
        if (x == s[i])
        {
            sameCount++;
        }
        else
        {
            diffCount++;
        }
        
        if (sameCount == diffCount)
        {
            answer++;
            
            if(i+1 < s.length())
            {
                x = s[i+1];
            }
            
            sameCount = 0;
            diffCount = 0;
        }
    }

    if (sameCount != 0 || diffCount != 0)
    {
        answer++;
    }

    return answer;
}

 

리펙토링 코드

#include <string>

using namespace std;

int solution(string s) {
    int answer = 0; // 분해된 문자열의 총 개수를 저장할 변수

    // 기준 글자(x)와 각 횟수를 저장할 상태 변수들
    char x; 
    int sameCount = 0; // 기준 글자와 같은 글자가 나온 횟수
    int diffCount = 0; // 기준 글자와 다른 글자가 나온 횟수

    // [리팩토링 포인트 1] 범위 기반 for문 사용
    // 인덱스(i) 없이 문자열 s에서 글자를 하나씩 순서대로 꺼내 변수 c에 담습니다.
    for (char c : s) 
    {
        // [리팩토링 포인트 2] 새로운 덩어리의 시작점 잡기
        // 두 카운트가 모두 0이라는 것은 '새로운 문자열 조각을 읽기 시작했다'는 뜻입니다.
        // 따라서 이때 처음 꺼낸 글자 c를 새로운 기준 글자 x로 설정합니다.
        if (sameCount == 0 && diffCount == 0) 
        {
            x = c;
        }

        // 현재 읽은 글자(c)가 기준 글자(x)와 같은지 다른지 판별하여 카운트를 올립니다.
        if (x == c) 
        {
            sameCount++; // 기준 글자와 같으면 sameCount 1 증가
        } 
        else 
        {
            diffCount++; // 기준 글자와 다르면 diffCount 1 증가
        }
        
        // 두 카운트가 같아지는 바로 그 순간, 문자열을 하나로 분리합니다.
        if (sameCount == diffCount) 
        {
            answer++;       // 문자열 조각 개수 1 증가
            sameCount = 0;  // 다음 조각을 다시 처음부터 세기 위해 0으로 초기화
            diffCount = 0;  // 다음 조각을 다시 처음부터 세기 위해 0으로 초기화
            
            // [리팩토링 포인트 3] 다음 기준 글자(s[i+1])를 미리 찾을 필요가 없습니다.
            // 루프가 다음 바퀴를 돌 때, 위쪽의 (sameCount == 0 && diffCount == 0) 조건에 걸려 
            // 자연스럽게 다음 글자가 새로운 기준 글자(x)로 설정되기 때문입니다.
        }
    }

    // [리팩토링 포인트 4] 남은 짜투리 처리 로직 간소화
    // 반복문이 다 끝났는데 sameCount가 0보다 크다는 것은, 
    // 카운트가 같아지지 않아서 미처 분리되지 못한 찌꺼기 글자가 남아있다는 뜻입니다.
    if (sameCount > 0) 
    {
        answer++; // 이 남은 부분도 하나의 조각으로 인정하여 더해줍니다.
    }

    return answer; // 최종 조각 개수 반환
}

주요 리팩토링 포인트

  1. 불필요한 변수 제거: 사용하지 않는 vector<string> save;와 주석 처리된 코드를 지워 메모리 낭비를 줄였습니다.
  2. 범위 기반 for문 사용 (Modern C++): s[i]처럼 인덱스로 접근하는 대신 for (char c : s) 문법을 사용해 코드를 훨씬 직관적으로 바꿨습니다.
  3. 미래(i+1)를 내다보는 대신, 현재에 집중하기: 이전 코드에서는 잘라낸 직후에 다음 글자(s[i+1])를 미리 찾아 x에 넣었습니다. 하지만 **"카운트가 모두 0으로 초기화되었을 때 읽는 글자가 곧 새로운 기준 글자다"**라는 규칙을 이용하면, 굳이 범위를 벗어날 위험이 있는 i+1을 확인할 필요가 없습니다.

회고

필요할 것 같은 변수를 일단 생성해두고 삭제 안하는 습관이 정말 무서운 것 같다... 이점은 빠르게 고쳐야 할 것 같다.

'코드테스트' 카테고리의 다른 글

[level 1] 체육복 - 42862  (0) 2026.03.19
[level 1] 숫자 짝꿍 - 131128  (0) 2026.03.17
[level 1] 옹알이 (2) - 133499  (0) 2026.03.16
[level 1] 기사단원의 무기 - 136798  (0) 2026.03.13
덧칠하기 - 161989  (0) 2026.03.09

+ Recent posts