본문 바로가기
Preparing Coding Test/Baekjoon

[Java/백준/투포인터] 1806번: 부분 합

by weero 2021. 6. 25.

문제

https://www.acmicpc.net/problem/1806

 

1806번: 부분합

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

www.acmicpc.net

연속된 수들의 부분합들 중에 그 합이 S 이상이 되는 것 중, 가장 짧은 것의 길이를 구하는 프로그램을 작성해야 한다.

 

 

참고한 부분은 아래 링크!

https://dev2som.tistory.com/135

 

[Java] 투 포인터(Two Pointers), 구간 합(Prefix Sum)

(출처 - 동빈나 유튜브) 배열의 특정된 연속 구간을 처리하는 경우에 사용하는 투 포인터와 구간합 알고리즘에 대해 알아보려 한다. 수열에서 합이 N인 연속부분수열 → Two Pointer N개의 정수로 구

dev2som.tistory.com

제목만 보면 구간 합을 참고했을 것 같지만 투포인터를 참고했다. 이유는 "합이 특정한 수" 이상이 되는  "가장 짧은 구간의 길이"를 구해야하기 때문이다.

 

위의 투포인터 코드를 따르되,

* 구간이 기존의 만족하는 구간 길이(answer)보다 작거나 같아야 한다.

* 아예 만족 못하는 경우가 있기 때문에 boolean 형의 flag를 만든다. flag가 false인 경우에는 만족하는 경우가 하나도 없다는 뜻이므로 0을 출력하게 한다.

를 새로 추가해주었다.

 

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		
		int N = Integer.parseInt(st.nextToken());
		int S = Integer.parseInt(st.nextToken());
		
		int answer = N;
		
		int[] arr = new int[N];
		st = new StringTokenizer(br.readLine(), " ");
		for(int i=0; i<N; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
		}
		
		int end = 0, sum = 0;
		boolean flag = false;
		for(int start = 0; start < N; start++) {
			while(sum < S && end < N && end-start <= answer) {
				sum += arr[end];
				end++;
			}
			if(sum >= S) {
				flag = true;
				answer = Math.min(answer, end-start);
			}
			
			sum -= arr[start];
			
		}
		if(!flag)
			answer = 0;
		System.out.println(answer);
		
		br.close();
	}

}