슬라이딩 윈도우 or 투 포인터 문제이다. 나는 슬라이딩 윈도우가 익숙하고 더 직관적이라고 생각해서, 슬라이딩 윈도우 방식으로 풀었다.
N이 10만이기 때문에 완전탐색으로 진행하면 시간복잡도가 O(N^2) 이고 10만 * 10만으로 100억번 연산이 나오기 때문에 문제를 해결할 수 없다. 슬라이딩 윈도우 방식으로 하면 약 O(2N) 정도로, 즉 O(N)에 해결할 수 있다.
해결방법은 간단하다. defaultdict를 활용해서, 각 숫자 당 카운트를 저장해 두고, right를 1씩 늘려가며 숫자 당 카운트를 집계하며 동시에 count변수로 최장길이를 구한다.
이 때 만약 특정 숫자 값이 K를 넘어서면, for문이 동작한다. 해당 K 위치까지 left 좌표를 1씩 올려가며, dict에서 숫자들의 카운트를 빼 준다. while문을 써도 되긴 하는데, 나는 무한루프 방어 목적으로 for문을 활용했다.
테스트 코드를 예로 들어 보겠다. 아래와 같은 조건에서, 굵게 표시된 곳까지 진행했고 count는 7이라고 하자.
3 2 5 5 6 4 4 5 7
left = 0, right = 6
여기서 right가 1 증가하면 5의 카운트가 3이 되고, K:2 보다 커지게 된다.
3 2 5 5 6 4 4 5 7
left = 0, right = 7
5의 카운트가 초과되었으므로, left를 5 다음 자리까지 올려 준다.
3 2 5 5 6 4 4 5 7
left = 3, right = 7
이렇게 K를 넘을 때마다 left를 올려 가며 right가 N에 도달할 때까지 진행해주면 된다. count는 직접 하나씩 증가시킬 필요 없이, (right - left) + 1 연산이 현재 수열 길이를 리턴하므로 이걸 활용하면 된다. 근데 사실 count 변수 없이 연산만으로도 짤 수 있긴 한데, 가독성을 위해 count 변수를 명시적으로 사용했다.
푸는데 1시간 조금 넘게 걸렸다. 이젠 문제를 보고 자연스럽게 알고리즘이 떠오를 수준은 되었지만, 여전히 구현력이 부족하다. 머리속에 맴도는 해결방법을 실제 코드로 옮기는 게 아직 좀 느리다. 열심히 반복훈련 하는 수 밖에 없을 것 같다.
'Algorithm > Sliding Window' 카테고리의 다른 글
[Baekjoon 12891 / Python / 실버2] DNA 비밀번호 (1) | 2024.09.25 |
---|