본문 바로가기
알고리즘

[백준] 1086번: 부분합 Java

by 랼랼 2022. 5. 24.

 

문제

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

 

입력

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

 

출력

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

 

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

 

1806번: 부분합

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

www.acmicpc.net

접근

투포인터를 이용하는 부분합을 구할 수 있습니다.

left와 right index값을 이용하여 left~right까지의 합을 합니다.

만약 합이 S보다 작다면 right를 증가시키고,

그 외의 경우에는 합이 S보다 작아질때까지 left를 증가시킵니다.

길이는 최소값을 취하고,

최종 길이가 초기값과 같다면 0을 출력하고, 아닐 경우 길이를 출력합니다.

구현

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

public class Main {
	//https://www.acmicpc.net/problem/1806
	
	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()); //도달해야 하는 합
		st=new StringTokenizer(br.readLine());
		int[] board = new int[n];//배열
		int max = 0;
		//배열 넣기
		for(int i=0;i<n;i++) {
			board[i]=Integer.parseInt(st.nextToken());
			max=Math.max(max, board[i]);
		}
		//max가 s보다 크면 한개로 충분함
		if(max>=s) {
			System.out.println(1);
		}else {
			//최대 길이
			int length = 100001;
			int left = 0;
			int right = 1;
			long sum = board[left];
			while(right<n) {
				//합 계산, right 증가
				sum+=board[right++];
				//합이 S보다 크다면
				if(sum>=s) {
					//sum이 s보다 작을 때까지 계산
					while(sum>=s) {
						sum-=board[left++];
						if(left==right) break;
					}
					//길이
					length = Math.min(length, right-left+1);
				}
			}
			System.out.println(length==100001?0:length);
		}
		br.close();
	}
}
반응형

댓글