홈 BOJ. 부분합 (1806)
글
취소

BOJ. 부분합 (1806)

문제: BOJ 1806 — 부분합

모든 수가 양수이므로 오른쪽 경계를 바깥으로 옮기면 구간의 합은 증가하고, 왼쪽 경계를 오른쪽으로 옮기면 합은 감소합니다. 배타적 오른쪽 경계를 하나씩 확장하고, 합이 S 이상이 되면 그 구간을 답 후보로 기록한 뒤 합이 계속 S 이상인 동안 왼쪽 경계를 이동합니다. 같은 끝점으로 끝나는 더 긴 구간은 답을 더 작게 만들 수 없습니다. 구간을 [left, right)로 표현하므로 길이는 정확히 right - left이며, 길이 1인 구간이나 배열의 첫/마지막 구간도 별도 처리 없이 올바르게 계산됩니다. 조건을 만족하는 구간이 없으면 답은 0입니다. 두 경계가 앞으로만 이동하므로 시간 복잡도는 O(N), 입력 배열을 저장하는 공간 복잡도는 O(N)입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import java.io.BufferedInputStream;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        FastScanner input = new FastScanner();
        int n = input.nextInt();
        long target = input.nextLong();
        int[] values = new int[n];
        for (int i = 0; i < n; i++) {
            values[i] = input.nextInt();
        }

        int minLength = n + 1;
        int left = 0;
        long sum = 0;
        int right = 0;
        while (right < n) {
            sum += values[right++];
            while (sum >= target) {
                minLength = Math.min(minLength, right - left);
                sum -= values[left++];
            }
        }

        System.out.println(minLength == n + 1 ? 0 : minLength);
    }

    private static class FastScanner {
        private final BufferedInputStream input = new BufferedInputStream(System.in);
        private final byte[] buffer = new byte[1 << 16];
        private int position;
        private int length;

        private int read() throws IOException {
            if (position == length) {
                length = input.read(buffer);
                position = 0;
                if (length == -1) {
                    return -1;
                }
            }
            return buffer[position++];
        }

        private int nextInt() throws IOException {
            return (int) nextLong();
        }

        private long nextLong() throws IOException {
            int c;
            do {
                c = read();
            } while (c <= ' ' && c != -1);

            long value = 0;
            while (c > ' ') {
                value = value * 10 + c - '0';
                c = read();
            }
            return value;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const fs = require('fs');
const input = fs.readFileSync(0, 'utf8').trim().split(/\s+/).map(Number);
const n = input[0];
const target = input[1];
const values = input.slice(2);

let minLength = n + 1;
let left = 0;
let sum = 0;
let right = 0;
while (right < n) {
  sum += values[right++];
  while (sum >= target) {
    minLength = Math.min(minLength, right - left);
    sum -= values[left++];
  }
}

console.log(minLength === n + 1 ? 0 : minLength);
이 글은 저자가 CC BY 4.0 라이선스로 배포합니다.