[알고리즘] 부분합

난이도

Gold 4

문제

10,000 이하의 자연수로 이루어진 길이 N짜리 수열이 주어진다. 이 수열에서 연속된 수들의 부분합 중에 그 합이 S 이상이 되는 것 중, 가장 짧은 것의 길이를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N (10 ≤ N < 100,000)과 S (0 < S ≤ 100,000,000)가 주어진다. 둘째 줄에는 수열이 주어진다. 수열의 각 원소는 공백으로 구분되어져 있으며, 10,000이하의 자연수이다.

출력

첫째 줄에 구하고자 하는 최소의 길이를 출력한다. 만일 그러한 합을 만드는 것이 불가능하다면 0을 출력하면 된다.

예제 입력

10 15
5 1 3 5 10 7 4 9 2 8

예제 출력

2

해설 및 후기

투포인터를 이용해서 풀 수 있다. i는 포인터의 앞부분, j는 포인터의 뒷부분을 의미하며, 부분합이 S를 넘는 구간까지 j를 증가시킨 후, 최소의 길이를 구하기 위해 부분합이 S를 넘는 구간 동안 i를 줄인다.

이를 j가 가능한 최대 길이까지 도달할 때까지 반복한다. 그 과정에서 j - i + 1의 크기가 가장 작은 것을 출력한다.

제출 코드

n, s = map(int, input().split())
nums = list(map(int, input().split()))
i = 0
j = 0
minVal = -1
tmp = 0
while(j < n):
    while(tmp < s and j < n):
        tmp += nums[j]
        j+=1
    if(j == n and tmp < s):
        break
    while(tmp >= s):
        tmp -= nums[i]
        i+=1
    if(minVal == -1):
        minVal = j - i + 1
    else:
        if(minVal > j - i + 1):
            minVal = j - i + 1

if(minVal == -1):
    print(0)
else:
    print(minVal)