카테고리 없음

[백준/파이썬][Gold IV] 부분합 - 1806

난쟁이 개발자 2025. 1. 3. 20:57
반응형

[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. 초기 상태

1. 초기 상태

2. while 문

쭉쭉쭉 해나가다 보면 답은 여러 개 나오지만, length = min(length, right - left) 의 조건에 따라 2가 가장 작은 수로 나오게 된다. 

elif right == N 조건을 생각해내지 못해서 코드를 참고하였다.

반응형