#문자열

프로그래머스 문제 중 문자열 분류에 해당하는 풀이를 다룬다. 현재 2개의 풀이가 있다.

문자열 학습 가이드

필요한 주제만 펼쳐서 문자열의 인덱스, 구간 처리, 비교와 탐색 패턴을 익힌다.

문자열 기본 개념

문자열은 문자가 순서대로 나열된 자료다. 각 문자는 위치를 가지므로 인덱스, 부분 문자열의 시작과 끝, 반복 여부를 정확히 관리해야 한다.

coding 문자열의 0부터 시작하는 인덱스와 s[2:6] 부분 문자열 범위를 보여주는 그림
Python의 슬라이스는 시작 인덱스는 포함하고 끝 인덱스는 포함하지 않는다.
  • 인덱스: 문자 하나의 위치를 가리키는 번호
  • 부분 문자열: 연속해서 잘라낸 문자열
  • 접두사: 문자열의 앞에서 시작하는 부분
  • 접미사: 문자열의 끝에서 끝나는 부분

입력의 대소문자, 공백, 특수문자를 그대로 비교할지 정규화할지 문제 조건에서 먼저 확인한다.

문자열 처리 패턴

문제의 목표가 문자열 변환인지, 문자 빈도인지, 특정 구간 탐색인지에 따라 상태를 다르게 유지한다.

문자열을 정규화하고 빈도를 세며 양끝 포인터로 스캔하는 세 가지 처리 패턴
정규화, 빈도 계산, 구간 스캔은 문자열 문제에서 반복해서 쓰는 패턴이다.
문제 조건우선 고려할 상태대표 활용
문자 순서를 무시하고 비교정렬 문자열·빈도 배열애너그램
문자 등장 횟수 비교`dict` 또는 26칸 배열문자 빈도·구성 확인
연속된 구간의 조건 유지슬라이딩 윈도우중복 없는 부분 문자열
양끝 문자를 비교왼쪽·오른쪽 포인터팰린드롬
패턴의 위치를 반복 검색문자열 탐색 알고리즘부분 문자열 검색
두 포인터와 팰린드롬

앞과 뒤에서 동시에 확인할 수 있는 문제는 두 포인터로 전체 문자열을 반복해서 뒤집거나 부분 문자열을 만들지 않고 처리할 수 있다.

raceca 문자열의 양끝에서 left와 right 포인터가 중앙으로 이동하며 문자를 비교하는 그림
양끝 문자를 비교한 뒤 포인터를 중앙으로 이동하면 팰린드롬을 한 번 순회로 확인할 수 있다.
left, right = 0, len(text) - 1
while left < right:
    if text[left] != text[right]:
        return False
    left += 1
    right -= 1

공백과 대소문자를 무시하는 문제라면 비교 전에 정규화할 범위를 명확히 정해야 한다. 두 포인터가 교차하면 모든 비교가 끝난 것이다.

문자열 복잡도와 선택 기준

문자열 길이를 `n`이라고 할 때, 한 번 순회하는 처리는 `O(n)`입니다. 매 위치에서 문자열 전체를 다시 만들거나 검색하면 `O(n²)`이 될 수 있습니다.

  • 문자 하나씩 처리하면 인덱스와 현재 상태를 유지
  • 연속 구간이면 슬라이딩 윈도우로 왼쪽 경계를 함께 갱신
  • 문자 종류가 제한적이면 고정 크기 빈도 배열 사용
  • 문자 순서가 중요하지 않으면 정렬 또는 해시 키로 특징을 정규화

Python 문자열은 불변이므로 반복해서 이어 붙이는 대신 리스트에 모은 후 `join`하는 방식이 긴 결과를 만들 때 유리하다.

자주 하는 실수
  • 슬라이스의 끝 인덱스가 포함된다고 착각하는 경우
  • 대소문자, 공백, 특수문자를 문제 조건과 다르게 처리하는 경우
  • 문자열을 반복해서 이어 붙여 불필요한 복사 비용을 만드는 경우
  • 문자 빈도만 같으면 애너그램이라고 판단해야 하는데 순서까지 비교하는 경우
  • 슬라이딩 윈도우에서 문자를 제거할 때 빈도 상태를 갱신하지 않는 경우

전체 문제 풀이 보기