알고리즘/백준

백준 1806번 부분합 - 자바(Java)

리콜 2024. 6. 27. 12:44

문제 링크

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

 


1. 문제

문제

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

2. 문제 관찰 과정 및 풀이

2-1. 문제 관찰 과정

누적합을 이용해서 문제를 풀었다. 

다만 left와 right를 관리할때 주어지는 배열이 정렬된 배열도 아닌데 

어떻게 나아가야하나 많은 고민을 하였다.

2-2. 문제 풀이

  1. 주어지는 n보다 1이큰 배열을 만든다
  2. index 0에는 0을 넣고 이전값들을 더하며 누적합 배열을 만든다.
  3. left = 0 , right =1 로 설정한다.
  4. arr[right] - arr[left]의 값을 s와 비교하며 만약 크거나 같다면
    1. 지금 몇개를 더 했는지 최솟값과 비교 후 저장
    2. left를 ++
  5. arr[right] - arr[left]의 값이 s보다 작다면
    1. right를 증가시켜 추가적으로 더해준다.
    2. 다만 right가 n과 같다면 이미 남은 모든 것을 더해도 s와 같거나 크지 못하니 그때는 종료한다.

3. 코드

package baekjoon;

import java.io.*;
import java.util.StringTokenizer;

public class boj_1806 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int n = Integer.parseInt(st.nextToken());
        int s = Integer.parseInt(st.nextToken());
        int[] arr =  new int[n + 1];
        int min = Integer.MAX_VALUE;

        StringTokenizer st2 = new StringTokenizer(br.readLine());
        for(int i = 1 ; i <= n; i++){
            arr[i] = Integer.parseInt(st2.nextToken()) + arr[i -1 ];
        }

        int left = 0;
        int right = 1;
        while (left < right) {
            if(arr[right] - arr[left] >= s){
                min = Math.min(min, right - left);
                left++;
                left = Math.min(n, left);
            }else if(arr[right] - arr[left] < s){
                if(right == n){
                    break;
                }else{
                    right++;
                    right = Math.min(n, right);
                }
            }
        }
        if(min == Integer.MAX_VALUE){
            bw.write("0");
        }else{
            bw.write(String.valueOf(min));
        }

        bw.flush();
        bw.close();
        br.close();
    }
}

3-1. 실행 결과

4. 여담

min값을 관리 안해줘서 21퍼에서 막혀서 계속 막혀있었다.

5 10

1 1 1 1 1

일때는 절대 못찾아서 0이 되어야했는데 이를 관리를 못해줬었다.

 

반응형