프로그래머스 12930 - 이상한 문자 만들기 (Lv.1)
핵심 접근 — 공백에서 리셋되는 단어 내 카운터로 짝/홀 판정
프로그래머스 12930 - 이상한 문자 만들기 (Lv.1)
출처: https://school.programmers.co.kr/learn/courses/30/lessons/12930
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 프로그래머스 12930 - 이상한 문자 만들기 (Lv.1)
// https://school.programmers.co.kr/learn/courses/30/lessons/12930
// 문제 설명
// 문자열 s는 한 개 이상의 단어로 구성되고, 각 단어는 하나 이상의 공백문자로 구분된다.
// 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾼 문자열을 반환하라.
// 제약 조건
// 문자열 전체가 아니라 단어별로 짝/홀수 인덱스를 판단한다. 첫 글자는 0번째(짝수).
// s는 알파벳과 공백으로만 구성되고, 공백이 연속으로 나올 수 있다.
// Example
// Input : "try hello world"
// Output: "TrY HeLlO WoRlD"
// 접근 — 공백에서 리셋되는 단어 내 카운터
// 인덱스를 문자열 전체가 아니라 단어 단위로 세는 것이 전부다.
// 1) 카운터 idx를 들고 순회, 공백을 만나면 idx = 0으로 리셋하고 그 글자는 건드리지 않는다.
// 2) 알파벳이면 idx의 홀짝으로 toupper/tolower를 골라 제자리에서 덮어쓰고 idx++.
// 3) 공백이 연속이면 리셋만 반복되므로 별도 분기 없이 처리된다.
// 시간 O(n), 공간 O(1) (입력 문자열을 그대로 변환)
#include <string>
#include <cctype>
using namespace std;
string solution(string s) {
int idx = 0; // 단어 내 알파벳 위치 (공백에서 0으로 리셋)
for (char& c : s) { // 참조로 받아 제자리 변환 — 결과 버퍼 불필요
if (c == ' ') { idx = 0; continue; } // 공백은 그대로 두고 카운터만 초기화
unsigned char u = static_cast<unsigned char>(c);
c = (idx % 2 == 0) ? toupper(u) : tolower(u); // 짝수 자리 대문자 / 홀수 자리 소문자
idx++;
}
return s;
}
정리
- 함정은 알고리즘이 아니라 인덱스의 기준점이다.
i % 2로 문자열 전체 위치를 쓰면 첫 단어만 맞고 두 번째 단어부터 어긋난다. 공백 개수가 짝수일 때만 우연히 맞아서, 예제"try hello world"(공백 1개씩)는 통과하고 채점에서 떨어지는 유형. “단어별”이라는 한 단어가 곧 상태 리셋 지점의 명세다. - 그래서
split으로 단어를 잘라 담을 필요가 없다. 잘라야 하는 이유는 단어 경계를 알기 위한 것뿐이고, 그 경계는 공백을 만나는 순간 이미 알 수 있다 — 카운터 하나로 분할을 대체하면 벡터 할당·재결합이 전부 사라진다. - 연속 공백·선행 공백이 별도 분기 없이 처리되는 것도 같은 이유다. 공백에서 하는 일이 “0으로 리셋”뿐이라 두 번 리셋해도 결과가 같다(멱등).
" ab cd "→" Ab Cd "로 실측 확인.split방식이면 빈 토큰 걸러내는 코드가 따로 필요해진다. for (char& c : s)로 참조 순회 + 제자리 변환이라 공간 O(1).s를 값으로 받는 시그니처라 원본 훼손 걱정도 없다. 강사 스타일의for (int i : s)는 값 복사라 읽기 전용일 때, 쓰기까지 하려면char&로 받아야 한다는 차이.toupper/tolower는 인자를int로 받되 음수 값은 UB라unsigned char로 캐스팅해 넘긴다. 이 문제는 알파벳·공백만 들어와 실질적 위험은 없지만, 반환형이int인 함수를char에 대입하는 계열은 캐스팅을 습관으로 두는 편이 안전하다.- 문자열을 문자 단위로 훑으며 상태를 바꾸는 계열은 12926 시저 암호와 골격이 같다 — 12926은 위치의 홀짝이 아니라 값을 밀어 바꾸고, 공백을 리셋 신호가 아니라 그냥 건너뛸 대상으로 쓴다. 공백을 만났을 때 무슨 일이 일어나는지가 두 문제의 갈림길.
- 검증: 예제 1개 + 경계(선행·연속 공백, 길이 1) 통과 (MSVC
/std:c++17컴파일·실행).
핵심 요약 — “단어별 짝/홀수”는 문자열 전체 인덱스가 아니라 공백에서 0으로 리셋되는 단어 내 카운터로 판정한다. 리셋이 멱등이라 연속·선행 공백이 분기 없이 처리되고,
split없이 카운터 하나로 O(1) 공간에 끝난다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.