커리큘럼/페이즈 1 · 기본기
3주차

문자열

불변 문자열을 다루는 법과, 이어붙이기가 만드는 함정을 배워요.

개념

문자열은 그냥 문자를 한 줄로 세워 놓은 배열이라고 보면 편해요. "code"c, o, d, e 네 칸짜리 배열이고, s[0]으로 첫 글자를 꺼내는 것도 배열이랑 똑같아요. 딱 하나 다른 점 — 이 배열은 칸을 못 고쳐요. 그래서 반복문에서 s += c로 글자를 이어붙이면 매번 배열 전체를 새로 복사하느라 O(n²)으로 느려져요. 이 함정만 조심하면 나머지는 배열 지식 그대로예요.두 언어 모두 문자열은 불변(immutable)이에요. 한 글자만 바꾸려 해도 새 문자열이 통째로 만들어져요. 이 사실 하나가 문자열 문제의 성능을 거의 결정해요.

기본 도구

하고 싶은 것JavaScriptPython
부분 잘라내기s.slice(a, b)s[a:b]
뒤집기[...s].reverse().join("")s[::-1]
나누기s.split(" ")s.split()
합치기arr.join("")"".join(arr)
문자 → 코드s.charCodeAt(i)ord(s[i])
코드 → 문자String.fromCharCode(n)chr(n)
소문자로s.toLowerCase()s.lower()
문자 코드 변환은 알파벳을 배열 인덱스로 쓸 때 자주 나와요. ord(c) - ord("a")a를 0, z를 25로 만들어 주니까, 길이 26짜리 배열 하나로 빈도수를 셀 수 있어요.

양끝에서 좁혀오기

팰린드롬처럼 앞뒤가 대칭인지 보는 문제는 양끝에 포인터를 두고 가운데로 좁혀오면 뒤집은 문자열을 새로 만들 필요가 없어요. 추가 메모리 없이 O(n)이에요. 8주차 투 포인터의 예고편이에요."abcba"가 회문인지 손으로 검사해 볼게요. 왼쪽 포인터 i와 오른쪽 포인터 j를 양끝에 두고, 두 글자가 같으면 안쪽으로 한 칸씩 좁혀요. 서로 지나칠 때까지 한 번도 안 어긋나면 회문이에요.
"abcba" 회문 검사 — i는 오른쪽으로, j는 왼쪽으로
인덱스 0 1 2 3 4
문자 a b c b a
i=0, j=4 : s[0]=a s[4]=a 같음 → i++, j--
i=1, j=3 : s[1]=b s[3]=b 같음 → i++, j--
i=2, j=2 : i < j 아님 → 멈춤
한 번도 안 어긋남 → 회문이에요 (true)
포인터가 가운데서 만나면(i < j가 깨지면) 검사를 끝내요. 홀수 길이면 정중앙 글자(c)는 자기 자신과 비교할 필요가 없어서 그냥 지나쳐요. 어긋나는 순간 바로 false를 돌려주면 되니까, 최악이라도 절반만 훑어서 O(n)이에요.

패턴 코드

조각을 모았다가 한 번에 합치기루프 안에서 += 하지 않는 것이 핵심이에요.
javascript
const parts = [];
for (const c of s) {
parts.push(transform(c));
}
return parts.join("");
알파벳을 인덱스로 쓰는 빈도수 배열
javascript
const count = new Array(26).fill(0);
for (const c of s) {
count[c.charCodeAt(0) - 97] += 1;
}
양끝에서 좁혀오며 대칭 확인
javascript
let i = 0;
let j = s.length - 1;
while (i < j) {
if (s[i] !== s[j]) return false;
i++;
j--;
}
return true;

이번 주 문제

이번 주 주제로 골라둔 문제예요. 채점은 프로그래머스에서 하고, 풀고 나면 여기에 체크해 두세요. 난이도 순으로 보여줘요.
프로그래머스 진행률
  • 문자열 내 p와 y의 개수
    Lv. 1풀기
  • 문자열 내림차순으로 배치하기
    Lv. 1풀기
  • 문자열 다루기 기본
    Lv. 1풀기
  • 문자열을 정수로 바꾸기
    Lv. 1풀기
  • 신규 아이디 추천
    Lv. 1풀기
  • 문자열 나누기
    Lv. 1풀기
  • 이진 변환 반복하기
    Lv. 2풀기

셀프 체크

다음 주로 넘어가기 전에 소리 내어 답해 보세요. 막히면 그 부분이 아직 덜 익은 개념이에요.
  1. 루프에서 s += c를 10만 번 하면 왜 느린지, 대안은 무엇인지 설명할 수 있는가?
  2. ord(c) - ord("a")가 왜 유용한가?
  3. 문자열의 한 글자만 바꾸려면 어떤 절차를 거쳐야 하는가?