LeetCode/Grind169
424. Longest Repeating Character Replacement ★★★★★
hyunkookim
2025. 4. 4. 09:32
424. Longest Repeating Character Replacement
이 문제는 슬라이딩 윈도우 [Sliding Window Variable Size] + 해시맵을 활용해서 풀 수 있어요.
핵심은 윈도우 안의 가장 많이 나온 문자를 기준으로
나머지를 바꾸는 데 k번 이하로 가능한지 체크하는 것입니다.
✅ 아이디어 요약:
- 윈도우 내 가장 많이 나온 문자 수 = max_count
- 현재 윈도우 크기 = r - l + 1
- 바꿔야 하는 문자 수 = 전체 윈도우 크기 - max_count
- 이 값이 k보다 작거나 같을 때만 윈도우 유지, 아니면 왼쪽 포인터 이동
✅ 코드 (주석 포함)
from collections import defaultdict
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
l = 0
max_count = 0 # 윈도우 안에서 가장 자주 등장하는 문자 수
count = defaultdict(int) # 각 문자의 등장 횟수 저장
max_len = 0
for r in range(len(s)):
count[s[r]] += 1
max_count = max(max_count, count[s[r]]) # 윈도우 내 최빈 문자 수 업데이트
# (윈도우 크기 - 최빈 문자 수) > k → 교체 범위 초과 → 왼쪽 이동
while (r - l + 1) - max_count > k:
count[s[l]] -= 1 # 왼쪽 문자 제거
l += 1 # 왼쪽 포인터 오른쪽으로 이동
max_len = max(max_len, r - l + 1) # 현재 윈도우 길이로 최대값 갱신
return max_len
🔍 예제 분석
예제 1: s = "XYYX", k = 2
- 'XYYX' 전체를 'XXXX' 또는 'YYYY'로 만들 수 있음 → 정답: 4
예제 2: s = "AAABABB", k = 1
- 'AABAB' 구간에서, 하나의 B를 A로 바꾸면 'AAAAA' → 길이 5 → 정답: 5
⏱️ 시간복잡도
- O(n) – 슬라이딩 윈도우 내에서 각 문자는 최대 한 번씩 왼쪽으로 나가므로 전체는 선형 시간
최종 코드
from collections import defaultdict
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
# k 번 바꿀 수 있음
charCount = defaultdict(int) # 각 문자의 등장 횟수를 저장할 딕셔너리
l_idx = 0 # 슬라이딩 윈도우의 왼쪽 포인터
longest = 0 # 조건을 만족하는 가장 긴 부분 문자열의 길이 저장
maxCount = 0 # 현재 윈도우 내에서 가장 많이 등장한 문자 개수 (=최빈 문자)
for r_idx in range(len(s)): # 오른쪽 포인터를 0부터 끝까지 이동시키며 윈도우 확장
charCount[s[r_idx]] += 1 # 현재 문자의 개수 +1
maxCount = max(maxCount, charCount[s[r_idx]]) # 최빈 문자 수 갱신
# 윈도우 전체 길이 > 최빈 문자 수 + k → 바꿔도 안 됨 → 윈도우 줄이기
while maxCount + k < (r_idx - l_idx + 1): # 윈도우 사이즈가 maxCount + k보다 크면
# 지금 left 글자를 없애야 하니, 우선 charCount 에서는 줄이고
charCount[s[l_idx]] -= 1
# maxCount = max(maxCount, charCount[s[l_idx]])
# → 이건 사실 필요 없음 (최대값이 줄어들 수 있기 때문, 다시 계산해야 정확)
# 하지만 실제 정답에는 영향을 거의 안 줌
# → 정확하려면 윈도우 내부에서 maxCount를 다시 계산해야 함
# 다만, 매번 계산하면 시간 복잡도가 올라가므로 최대값 유지 방식이 더 효율적
l_idx += 1 # 다음 단어로 이동, l_idx 증가
# 현재 윈도우의 길이와 비교해서 최대 길이 갱신
longest = max(longest, r_idx - l_idx + 1)
return longest
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
# 최대 k 번 교체 가능
# return 최장 부분수열(반복되는 문자)의 길이
# 문자의 개수 counting -> dict 사용
chCount = defaultdict(int)
longest = 0
maxCount = 0 # 최대 문자 수
left =0
for right in range(len(s)):
chCount[s[right]] +=1
maxCount = max(maxCount, chCount[s[right]])
# 윈도우 크기 > 가장긴글자수 + k번교체 이면,
# 같게 만들기 위해서, left를 증가시켜서 윈도우를 작게..
while (right-left+1) > maxCount + k:
# left 증가하기 전에, 우선 chCount 에서 해당 글자 제거 후.
chCount[s[left]] -=1
# maxCount 도 다시 갱신
maxCount = max(maxCount, chCount[s[left]])
# left 증가
left +=1
longest = max(longest, right-left+1)
return longest