https://school.programmers.co.kr/learn/courses/30/lessons/140108
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
문제 풀이: 문자열 나누기
문제를 해결하기 위해 문자열을 차례로 탐색하면서 규칙에 따라 분리합니다.
규칙은 다음과 같습니다:
- 첫 글자를 기준으로 그룹화:
- 첫 글자를 x로 설정.
- x의 등장 횟수와 x가 아닌 글자의 등장 횟수를 셈.
- 횟수 비교:
- x와 x가 아닌 글자의 등장 횟수가 같아질 때 문자열을 분리.
- 남은 문자열 반복:
- 분리한 문자열을 제거하고, 남은 부분에 대해 동일한 작업을 수행.
- 남은 문자열 처리:
- 더 이상 읽을 글자가 없거나 횟수가 다르면 해당 문자열을 분리.
코드 구현
def solution(s):
answer = 0 # 분리된 문자열 개수
count_x = 0 # x의 등장 횟수
count_other = 0 # x가 아닌 글자의 등장 횟수
# 문자열을 순차적으로 탐색
while s:
x = s[0] # 첫 글자
count_x = 0
count_other = 0
for i, char in enumerate(s):
if char == x:
count_x += 1
else:
count_other += 1
# x와 다른 글자의 등장 횟수가 같으면 분리
if count_x == count_other:
answer += 1
s = s[i + 1:] # 분리된 부분 제거
break
else:
# 남은 문자열 처리
answer += 1
break
return answer
코드 흐름 설명
- while s:
- 문자열 s가 남아 있는 동안 반복.
- 첫 글자 설정:
- x = s[0]으로 기준 글자를 설정.
- count_x와 count_other로 각 글자들의 등장 횟수를 저장.
- 횟수 비교 및 분리:
- 문자열을 순차적으로 탐색하며 x와 다른 글자의 횟수를 비교.
- 두 횟수가 같아지는 순간 문자열을 분리.
- break의 역할
if count_x == count_other:
answer += 1
s = s[i + 1:] # 분리된 부분 제거
break
break는 count_x == count_other 조건이 충족된 즉시 for 루프를 중단합니다.
- 이렇게 하면:
- answer를 올리고,
- 문자열 s를 남은 부분(s[i + 1:])으로 잘라,
- 다음 while 루프에서 남은 문자열을 처리.
5.for-else 동작 분석
- for 문:
- 문자열 s를 순회하면서 조건(count_x == count_other)이 충족되면 break를 통해 분리 작업을 수행합니다.
- 이때 break가 발생하면 else 블록은 실행되지 않습니다.
- else 문:
- for 문이 모든 글자를 탐색했지만, count_x == count_other 조건이 충족되지 않을 때 실행됩니다.
- 남은 문자열이 더 이상 나눌 수 없는 상태로, 이 문자열 자체를 하나의 분리된 문자열로 간주하고 answer를 증가시킵니다.
- break는 문자열 탐색을 완료했음을 나타내고 while 루프를 종료합니다.
예시 입력:
s = "banana"
초기 상태
- answer = 0 (분리된 문자열 개수)
- count_x = 0 (x의 등장 횟수)
- count_other = 0 (x가 아닌 글자의 등장 횟수)
- s = "banana"
1번째 루프:
- x = s[0] → x = 'b' (첫 글자)
- count_x = 0, count_other = 0 (초기화)
문자열 탐색 (for 루프):
- 1번째 글자: 'b'
- 'b' == 'b' → count_x += 1 → count_x = 1
- 2번째 글자: 'a'
- 'a' != 'b' → count_other += 1 → count_other = 1
- count_x == count_other (1 == 1) → 문자열 분리.
- answer += 1 → answer = 1
- s = s[2:] → s = "nana"
2번째 루프:
- x = s[0] → x = 'n'
- count_x = 0, count_other = 0 (초기화)
문자열 탐색 (for 루프):
- 1번째 글자: 'n'
- 'n' == 'n' → count_x += 1 → count_x = 1
- 2번째 글자: 'a'
- 'a' != 'n' → count_other += 1 → count_other = 1
- count_x == count_other (1 == 1) → 문자열 분리.
- answer += 1 → answer = 2
- s = s[2:] → s = "na"
3번째 루프:
- x = s[0] → x = 'n'
- count_x = 0, count_other = 0 (초기화)
문자열 탐색 (for 루프):
- 1번째 글자: 'n'
- 'n' == 'n' → count_x += 1 → count_x = 1
- 2번째 글자: 'a'
- 'a' != 'n' → count_other += 1 → count_other = 1
- count_x == count_other (1 == 1) → 문자열 분리.
- answer += 1 → answer = 3
- s = s[2:] → s = "" (빈 문자열)
루프 종료
- s가 빈 문자열이므로 while s 조건이 거짓이 되어 종료.
최종 결과:
- answer = 3
핵심 알고리즘: 그리디 알고리즘
- 문자열을 탐색하면서 가능한 가장 작은 단위로 문자열을 나눔.
- 분리 시마다 나머지 문자열을 다시 처리.
출제 의도
- 문자열 탐색 및 조건 처리:
- 문자열을 순차적으로 탐색하며 조건을 만족하는 지점을 찾아 처리.
- 그리디 접근법 활용:
- 각 단계에서 가능한 가장 작은 크기로 문자열을 분리.
- Python의 문자열 조작 활용:
- 슬라이싱(s[i+1:])과 조건문을 사용해 문자열을 처리.
시간 복잡도
- O(n):
- 문자열을 한 번 순차적으로 탐색.
- 각 분리 작업은 일정 시간 소요.
공간 복잡도
- O(1):
- 문자열 s를 인덱스로 처리하며, 추가적인 메모리 사용이 적음.
여기서 잠깐! for-else 구조의 동작
for-else 문이란?
- for 루프가 정상적으로 종료되면(즉, break를 만나지 않고 끝까지 실행되면) else 블록이 실행됩니다.
- 만약 for 루프가 중간에 break로 종료되면, else 블록은 실행되지 않습니다.
for-else 문 기본 구조
for element in iterable:
# 반복문 내부
if some_condition:
break # break가 실행되면 else는 실행되지 않음
else:
# for 루프가 정상적으로 종료되면 실행
# break가 실행되지 않은 경우에만 실행됨
for-else 동작 원리
- for 루프 정상 종료:
- for 루프가 iterable의 모든 요소를 순회한 뒤 종료되면 else 블록이 실행됩니다.
- break로 종료:
- break가 실행되면 루프가 즉시 종료되고, else 블록은 건너뜁니다.
예제
1. else 실행 예시
for num in range(5):
print(num)
else:
print("루프가 정상적으로 종료되었습니다.")
출력:
0
1
2
3
4
루프가 정상적으로 종료되었습니다.
- break가 없으므로 루프가 정상적으로 종료되고, else 블록이 실행됩니다.
2. break로 종료
for num in range(5):
print(num)
if num == 2:
break
else:
print("루프가 정상적으로 종료되었습니다.")
출력:
0
1
2
- break로 루프가 중단되었으므로 else 블록은 실행되지 않습니다.
for-else 실제 활용 예
소수 판별
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False # 나누어 떨어지면 소수가 아님
else:
return True # for 루프가 끝까지 실행되면 소수
설명:
- 숫자가 2부터 제곱근까지 나누어 떨어지지 않으면 else 블록이 실행되어 소수임을 반환합니다.
찾고자 하는 값 탐색
def find_value(lst, target):
for val in lst:
if val == target:
print("값을 찾았습니다!")
break
else:
print("값을 찾지 못했습니다.")
설명:
- 리스트를 순회하며 target을 찾으면 break로 루프 종료.
- 값을 찾지 못하면 else 블록 실행.
for-else의 특징
- else는 루프의 성공 조건을 처리하는 데 유용합니다.
- 단순한 if-else와는 다릅니다. for-else는 루프의 흐름에 의존합니다.
- break 여부에 따라 동작이 결정됩니다.
for-else의 장점
- 루프 내부에서 조건 검사를 수행하고, 추가 처리가 필요한 경우 깔끔한 코드 작성 가능.
- break와 정상 종료에 따른 처리를 명확히 구분할 수 있음.
'코딩테스트 > 프로그래머스' 카테고리의 다른 글
프로그래머스 | Python | DP:테뷸레이션 | 거스름돈 (Lv.3) (0) | 2025.03.03 |
---|---|
프로그래머스 | Python | 완전탐색 | 피로도 (Lv.2) (0) | 2025.03.02 |
프로그래머스 | Python | 단순구현 | 둘만의 암호 (Lv.1) (0) | 2025.02.27 |
프로그래머스 | Python | Hash, Greedy | 대충 만든 자판 (Lv.1) (0) | 2025.02.27 |
프로그래머스 | Python | Brute Froce | [PCCE 기출문제] 9번 / 이웃한 칸 (Lv.1) (0) | 2025.02.27 |