문제
https://www.acmicpc.net/problem/1806
1806번: 부분합
첫째 줄에 N (10 ≤ N < 100,000)과 S (0 < S ≤ 100,000,000)가 주어진다. 둘째 줄에는 수열이 주어진다. 수열의 각 원소는 공백으로 구분되어져 있으며, 10,000이하의 자연수이다.
www.acmicpc.net
문제 요약
길이가 N인 수열을 입력 받고 연속된 수들의 부분 합의 크기가 S이상인 부분 수열 중 길이가 가장 짧은 수열의 길이를 출력한다.
+ 위 조건을 만족하는 부분합이 없다면 0을 출력한다.
코드
N, S = map(int, input().split())
# 수열의 길이 N, S 이상의 부분수열의 합
arr = list(map(int, input().split()))
# 수열
left = 0
right = 1
# arr의 인덱스를 가리킬 투 포인터
pre = [0] * (N + 1)
# pre[i]는 arr[i]이전 까지의 부분합
for i in range(N):
pre[i + 1] = pre[i] + arr[i]
ans = N + 1
# 부분 합이 S이상인 부분 수열 중 가장 짧은 길이 (초기 값은 수열의 길이 + 1)
leng = 1
# 현재 구간의 길이
while right <= N:
total = pre[right] - pre[left]
# 현재 구간의 부분합
if total < S:
# 부분합이 S보다 작으면
right += 1
# right 포인터를 오른쪽으로 한 칸 이동
leng += 1
# 구간 길이 증가
else:
# 부분합이 S 이상이면
if leng < ans:
# 이전까지의 가장 짧은 길이보다 더 짧다면
ans = leng
left += 1
# left 포인터를 오른쪽으로 한 칸 이동
leng -= 1
# 구간 길이 감소
if ans == N + 1:
# ans가 초기값 그대로라면 (조건에 만족하는 부분 수열이 없었다면)
print(0)
else:
print(ans)
코드 설명
1. arr[0]부터 arr[i] 이전까지의 부분합을 갖는 배열 pre[i]를 설정한다.
2. 현재 구간의 부분합이 S보다 작으면 right 포인터를, 크거나 같으면 left 포인터를 이동시킨다.
3. 부분합이 S이상 일 때, 이전까지 가장 짧았던 길이보다 더 짧다면 ans를 갱신한다.
4. right 포인터가 N을 초과하면 탐색을 종료한다.
5. ans가 초기 값 그대로라면, 조건에 만족하는 부분 수열이 없었다는 것이므로 0을 출력하고, 아니라면 ans를 출력한다.
'Algorithm Problems > 투 포인터' 카테고리의 다른 글
[백준/Python] 26091번: 현대모비스 소프트웨어 아카데미 (1) | 2023.09.24 |
---|---|
[백준/Python] 3151번: 합이 0 (0) | 2023.09.23 |
[백준/Python] 3273번: 두 수의 합 (0) | 2023.09.18 |
[백준/python] 14465번: 소가 길을 건너간 이유 5 (2) | 2023.08.18 |
[백준/python] 2467번: 용액 (4) | 2023.08.17 |