s, return the maximum length of a substring such that it contains at most two occurrences of each character.
Example 1:
Output: 4
Explanation:
The following substring has a length of 4 and contains at most two occurrences of each character: "bcbbbcba".
Example 2:
Output: 2
Explanation:
The following substring has a length of 2 and contains at most two occurrences of each character: "aaaa".
Constraints:
2 <= s.length <= 100s consists only of lowercase English letters.해시 테이블, 문자열, 슬라이딩 윈도우
주어진 문자열 s에서 각 문자가 최대 2번 이하로 등장하는 가장 긴 부분 문자열(substring)의 길이를 구하는 문제입니다.
s (길이 2 ~ 100)이 문제는 슬라이딩 도우(Sliding Window, 두 포인터) 알고리즘과 **해시 (Hash Map)**을 조합하여 해결합니다.
defaultdict) 선택 이유: 현재 도우 내에 포함된 각 문자의 등장 수를 O(1) 시간에 기록하고 확인하기 위해 사용합니다. 알파 소문자만 들어오므로 크기 26의 배열을 써도 무방하지만, 해시 이 구현이 더 간결합니다.right)를 한 칸씩 오른쪽으로 이동하며 도우를 확장합니다.left)를 오른쪽으로 이동하며 도우를 축소하여 조건을 복구합니다.n = len(s): 문자열의 전체 길이 저장k = 2: 허용되는 최대 등장 수 상수화left = 0, right = 0: 도우의 시작과 끝을 가리키는 두 포인터 초기화 (초기 도우는 빈 구간 [0, 0))counts = defaultdict(int): 현재 도우 내 문자별 등장 수를 저장할 해시answer = 0: 정답(최대 길이)을 저장할 변수while right != n)right가 문자열 끝(n)에 도달할 때까지 반복합니다.counts[s[right]] += 1로 현재 오른쪽 문자를 도우에 포함시키고 개수를 증가시니다.while counts[s[right]] > k)s[right]의 개수가 k(2)를 초과했다면 조건 위반 상태입니다.counts[s[left]] -= 1로 왼쪽 문자를 도우에서 제거하고, left += 1로 왼쪽 경계를 오른쪽으로 한 칸 이동시니다.s[right]의 개수가 2 이하가 될 때까지 반복하여 유효한 도우 상태로 만듭니다.right += 1: 오른쪽 포인터를 다음 위치로 이동시니다 (도우 범위는 [left, right)).answer = max(answer, right - left): 현재 유효한 도우의 길이(right - left)와 기존 최대 길이 중 큰 값으로 정답을 신합니다.answer 반환.시간 복잡도: O(N)
right 포인터는 0부터 N-1까지 최대 한 번씩만 오른쪽으로 이동합니다.left 포인터 역시 0부터 N-1까지 최대 한 번씩만 오른쪽으로 이동합니다.공간 복잡도: O(1) 또는 O(알파 종류 수)
counts 해시 에는 최대 26개의 소문자 키만 들어갈 수 있습니다. 입력 크기 N에 비례하지 않고 상수 크기로 고정니다.while 루프 중으로 유효성 보장: if가 아닌 while을 사용하여 왼쪽 포인터를 이동시키는 이유는, 왼쪽 포인터를 한 칸 옮겼음에도 여전히 조건을 위반할 수 있기 때문입니다(예: aaa에서 오른쪽이 마지막 a를 가리킬 때, 왼쪽을 한 칸 옮기면 aa가 되어 여전히 위반).[left, right) (left 포함, right 미포함) 형태로 관리니다. right를 증가시킨 후 길이를 right - left로 계산하는 것이 이 정의와 일치합니다.class Solution:
def maximumLengthSubstring(self, s: str) -> int:
n = len(s)
k = 2
left = 0
right = 0
counts = defaultdict(int)
answer = 0
while right != n:
counts[s[right]] += 1
while counts[s[right]] > k:
counts[s[left]] -= 1
left += 1
right += 1
answer = max(answer, right - left)
return answer