[Gold IV] 부분합 - 1806
성능 요약
메모리: 121100 KB, 시간: 112 ms
분류
누적 합, 두 포인터
제출 일자
2025년 1월 3일 20:05:56
문제 설명
10,000 이하의 자연수로 이루어진 길이 N짜리 수열이 주어진다. 이 수열에서 연속된 수들의 부분합 중에 그 합이 S 이상이 되는 것 중, 가장 짧은 것의 길이를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N (10 ≤ N < 100,000)과 S (0 < S ≤ 100,000,000)가 주어진다. 둘째 줄에는 수열이 주어진다. 수열의 각 원소는 공백으로 구분되어져 있으며, 10,000이하의 자연수이다.
출력
첫째 줄에 구하고자 하는 최소의 길이를 출력한다. 만일 그러한 합을 만드는 것이 불가능하다면 0을 출력하면 된다.
풀이
N, M = map(int, input().split())
lst = list(map(int, input().split()))
left, right = 0, 0
target = 0
length = N + 1
while True :
if target >= M :
length = min(length, right - left)
target -= lst[left]
left += 1
elif right == N :
break
else :
target += lst[right]
right += 1
if length == N + 1 :
print(0)
else :
print(length)
left, right = 0, 0
target = 0
length = N + 1
left, right : 슬라이딩 윈도우의 시작과 끝을 나타내는 인덱스
target : 현재 슬라이딩 윈도우 내 요소의 합
length : 조건을 만족하는 부분 리스트의 최소 길이를 저장.
while True :
if target >= M :
length = min(length, right - left)
target -= lst[left]
left += 1
elif right == N :
break
else :
target += lst[right]
right += 1
1. target >= M :
- 현재 target이 목표M 이상이면, 최소 길이를 갱신
- 그 다음 현재 길이를 최소 길이로 갱신
- target 에서 왼쪽 경계에 있는 요소를 뺀 후, left를 오른쪽으로 한 칸 이동 시킴
2. right == N 조건 :
- right 가 리스트 끝에 도달했으면 반복 종료. 더 이상 확장할 윈도우가 없음을 의미
3. 그 외 :
- target < M 이면 윈도우를 확장하기 위해 right 현 위치의 수를 target에 더하고, right를 오른쪽으로 한 칸 이동함.
1. 초기 상태
2. while 문
쭉쭉쭉 해나가다 보면 답은 여러 개 나오지만, length = min(length, right - left) 의 조건에 따라 2가 가장 작은 수로 나오게 된다.
elif right == N 조건을 생각해내지 못해서 코드를 참고하였다.