
코딩테스트 문자열 정리입니다.
헷갈리는 것만!! 정리했어요 (앞으로도 추가될 예정!)
| # | 문제 | 출처 | 링크 |
|---|---|---|---|
| 1 | 모음사전 | 프로그래머스 | 바로가기 |
| 2 | 문자열 압축 | 프로그래머스 (2020 카카오) | 바로가기 |
| 3 | 제곱수 판별하기 | 프로그래머스 | 바로가기 |
| 메서드 | 하는 일 |
|---|---|
s.split() | 공백 기준으로 나누기 ("a b c".split() → ['a','b','c']) |
s.split(",") | 특정 기준으로 나누기 |
"구분자".join(list) | 리스트를 문자열로 합치기 |
s.strip() / lstrip() / rstrip() | 양끝 / 왼쪽 / 오른쪽 공백·문자 제거 |
s.replace(old, new) | 문자(열) 치환 (전부 다 바꿈) |
💡 문자열 누적은
result += c대신 리스트에 모았다가"".join(...)하자.
+=를 반복하면 매번 새 문자열을 만들어 O(n²)이 되지만,join은 O(n)이다.
| 메서드 | 하는 일 | 못 찾으면 | 리스트 가능? |
|---|---|---|---|
index(x) | 첫 번째 위치 | 에러(ValueError) | ✅ 가능 |
find(x) | 첫 번째 위치 | -1 | ❌ 문자열만 |
rfind(x) | 마지막 위치 | -1 | ❌ 문자열만 |
count(x) | 개수 세기 | 0 | ✅ 가능 |
startswith(x) / endswith(x) | 접두사 / 접미사 판별 | — | ❌ 문자열만 |
⚠️ 가장 헷갈리는 포인트
find는 문자열 전용 (리스트엔find없음). 리스트에서 위치 찾을 땐index.- 없을 때 동작이 다르다:
find→-1/index→ 에러. "없으면 -1"이 필요하면find.
s = "banana"
s.find("a") # 1 (첫 번째)
s.rfind("a") # 5 (마지막)
s.find("x") # -1 (없으면 -1)
words = ["a", "b", "c"]
words.index("b") # 1 (리스트도 index는 됨)
count는 겹치지 않게 셉니다.
"banana".count("a") # 3
"banana".count("na") # 2
"aaaa".count("aa") # 2 ← aa / aa 로 끊어 셈 (겹쳐서 3 아님!)
문자열 안에 뭐가 들었는지 검사하는 is~ 시리즈입니다. (빈 문자열은 전부 False)
| 메서드 | True 조건 |
|---|---|
isalpha() | 문자만 |
isdigit() | 숫자만 |
isalnum() | 문자 + 숫자 |
islower() / isupper() | 전부 소문자 / 대문자 |
lower() / upper() | 소문자 / 대문자로 변환 |
타입 자체를 확인할 땐 ↓
| 방법 | 결과 / 용도 |
|---|---|
type(a) | <class 'str'> |
type(a).__name__ | 'str' (이름 문자열로) |
isinstance(num, int) | True — 특정 타입인지 검사할 땐 보통 이걸 씀 |
| 도구 | 하는 일 |
|---|---|
ord('a') | 문자 → 아스키 코드 (97) |
chr(97) | 아스키 코드 → 문자 ('a') |
'apple' < 'banana' | 사전순 비교 (True) |
sorted(s) | 정렬된 리스트 반환 |
sorted(words, key=len) | 길이순 정렬 |
Counter(s) | 각 문자 개수를 dict로 |
💡
sorted("banana")는['a','a','a','b','n','n']처럼 리스트가 나온다.
문자열로 되돌리려면"".join(sorted(s)).
from collections import Counter
Counter("banana") # Counter({'a': 3, 'n': 2, 'b': 1})
A, E, I, O, U로 만들 수 있는 길이 1~5짜리 단어를 사전순으로 늘어놨을 때 word의 순번을 구하는 문제. 만들 수 있는 단어는 5 + 25 + 125 + 625 + 3125 = 3905개뿐이라, 다 만들어서 정렬한 뒤 인덱스를 찾으면 끝난다.
itertools.product(중복 허용 순열)로 모든 조합을 만든다.
from itertools import product
def solution(word):
words = []
for length in range(1, 6):
for p in product("AEIOU", repeat=length):
words.append("".join(p)) # ('A','A','E') → "AAE"
words.sort()
return words.index(word) + 1 # 사전 순번은 1부터
product("AEIOU", repeat=2)는('A','A'), ('A','E') ...처럼 튜플로 나온다. 그래서"".join(p)로 문자열로 합쳐줘야 한다.
aabbaccc 같은 문자열을 1글자, 2글자, ... 단위로 잘라 압축했을 때 가장 짧은 길이를 구하는 문제. 자르는 단위(size)를 1 ~ len//2까지 다 시도하면 된다.
핵심 로직: 앞 덩어리를 저장해두고 → 같으면 count += 1, 다르면 (count가 2 이상이면 숫자를 붙여서) 이어붙이고 새 덩어리 시작.
def solution(s):
answer = len(s) # 안 줄어드는 경우(길이 1 등) 대비
for size in range(1, len(s) // 2 + 1):
compressed = ""
prev = s[:size]
count = 1
for j in range(size, len(s), size):
cur = s[j:j + size]
if cur == prev:
count += 1
else:
compressed += (str(count) if count > 1 else "") + prev
prev, count = cur, 1
compressed += (str(count) if count > 1 else "") + prev # 마지막 덩어리 처리!
answer = min(answer, len(compressed))
return answer
⚠️ 반복문이 끝난 뒤 마지막 덩어리를 한 번 더 이어붙이는 것을 빼먹기 쉽다.
count == 1일 땐 숫자를 안 붙이는 것도 주의(1ab가 아니라ab).
n이 어떤 자연수의 제곱이면 1, 아니면 2를 반환. √n이 정수인지만 보면 된다. is_integer()가 깔끔하다.
def solution(n):
return 1 if (n ** 0.5).is_integer() else 2
(n ** 0.5)는 float이고, float에는.is_integer()가 있어서4.0.is_integer()→True.math.sqrt(n)을 써도 된다.
| 키워드 | 기억할 것 |
|---|---|
find vs index | find는 문자열 전용·없으면 -1 / index는 리스트도 됨·없으면 에러 |
count | 겹치지 않게 셈 ("aaaa".count("aa") = 2) |
| 문자열 누적 | += 말고 리스트에 모아 "".join() (O(n²) → O(n)) |
sorted(s) | 리스트 반환 → 문자열은 "".join(sorted(s)) |
is~ 시리즈 | isalpha(문자) / isdigit(숫자) / isalnum(문자+숫자), 빈 문자열은 False |
| 타입 검사 | 특정 타입인지 볼 땐 isinstance(x, int) |
ord / chr | 문자 ↔ 아스키 코드 |
Counter(s) | 문자 개수를 dict로 한 방에 |
| 전수 생성 | 경우의 수가 적으면(모음사전 3905개) itertools.product로 다 만들고 정렬 |