[ProblemSolving] 백준 - 1806 부분합 (투포인터)

문제 링크

문제 설명


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

입력


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

출력


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

예제 입력1

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

예제 출력1

2

나의 풀이 1


투포인터으로 해결한다.

start, end 를 0으로 셋팅하고 end가 n이 될 때까지 반복문을 진행한다.

  1. end를 하나씩 이동하면서 temp에 누적하고, end를 1증가
  2. temp값이 s 이상이라면 length에 최소 길이를 구해준다.
    temp에서 start에 위치한 요소를 빼주고, start는 오른쪽으로 한칸씩 이동한다.
  3. end가 배열의 끝에 다다를 때까지 반복한다.
메모리시간
40748 KB172 ms

나의 코드


n, s = map(int, input().split())
arr = list(map(int, input().split()))

start , end = 0, 0
temp =0
length = n+1
while True:
    if temp >= s:
        length = min(length, end-start)
        temp -= arr[start]
        start += 1
    
    elif end == n:
        break
    
    else:
        temp += arr[end]
        end += 1
if length == n+1:
    print(0)
else:
    print(length)

다른 분 풀이 2


메모리시간
39756 KB116 ms

while 대신 for 반복문을 이용한 더 직관적이고 쉬운 코드인 것 같다.

코드

from sys import stdin

input = stdin.readline

def solve():

    N, S = map(int, input().split())

    arr = list(map(int, input().split()))

    inf = float('inf')
    left, sum_val, ans= 0, 0, inf

    for right in range(N):
        sum_val += arr[right]
        while sum_val - arr[left] >= S:
            sum_val -= arr[left]
            left += 1

        if sum_val >= S and ans > right - left:
            ans = right - left + 1

    print(ans if ans != inf else 0)
    return

solve()

좋은 웹페이지 즐겨찾기