Q 2015 수들의 합 4

💡 문제 요약 및 분석

정수 N 과 K 가 주어졌을 때, N 개의 정수가 들어가는 배열 A 에서 부분합이 K 가 되는 경우의 수를 출력하면 된다.

💡 알고리즘 설계

🔥 도저히 모르겠어서 답을 보고 풀었다. 시간 안에 풀려면 누적합 배열 + Map 을 활용해야 한다.

  1. 입력

    • 표준입력 받는 숫자를 누적합한 배열 sum 을 만든다.
  2. 연산

    부분합 k 를 어떻게 구할 것인가가 관건이었는데, 시간 안에 풀려면 다음과 같은 공식을 생각해냈어야 한다.

     sum[j] - sum[i - 1] = k
     sum[j] - k = sum[i - 1]
    

    즉 누적합 배열 sum[j] - K 의 값을 갖는 sum[i - 1] 인덱스가 존재한다면 count 변수에 더하면 된다. 이를 판단하기 위해서는 Map 이 필요하다.

    • HashMap 생성하여 기본값으로 map.put(0,1) 넣기. 왜냐하면 sum[j] - K == 0 일 때가 있을 수 있기 때문에 미리 값을 넣어주는 것이다.
    • for 문으로 N 까지 반복한다. (최대 200,000번 수행)
    • map 에서 sum[i] - K 의 값을 key 로 갖는 값을 찾는데, 없으면 0을, 있으면 value 를 count 에 더한다.
    • map.put(sum[i], map.getOrDefault(sum[i],0) + 1) 하여 확인이 끝난 sum[i] 인덱스를 key 로 넣어준다. 이 때 value 는 1을 넣어주는데, 다음 연산에서 해당 key 가 조회되었을 때 count 하기 위함이다.
  3. 출력

    • count 변수를 출력한다.

💡 코드

import java.io.*;
import java.util.HashMap;
import java.util.Map;
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());
        long K = Long.parseLong(st.nextToken());

        long[] sum = new long[N + 1];
        st = new StringTokenizer(br.readLine());
        for (int i = 1; i < N + 1; i++) {
            sum[i] += sum[i - 1] + Long.parseLong(st.nextToken());
        }

        Map<Long, Long> map = new HashMap<>();
        map.put(0L,1L);
        long count = 0;
        for (int i = 1; i < N + 1; i++) {
            count += map.getOrDefault(sum[i] - K, 0L);
            map.put(sum[i], map.getOrDefault(sum[i], 0L) + 1);
        }
        System.out.println(count);
    }
}

💡 시간 복잡도, 공간 복잡도

시간 복잡도공간 복잡도
O(n)O(n)

💡 느낀점 및 기억할 정보

👩🏻‍💻 부분합 알고리즘

배열의 일부 구간의 합을 빠르게 구할 수 있게 해주는 알고리즘이다. N 개의 원소로 이루어진 배열이 주어졌을 때, 반복문으로 부분 배열의 합을 구하려면 O(n) 걸리는데, 부분합을 이용하면 모든 부분합을 O(1) 에 구할 수 있다.

1️⃣ 1차원 배열 arr 이 주어졌을 때, 일단 각 원소를 누적합한 배열 sum 을 새로 만든다.

2️⃣ arr 배열의 i항부터 j항까지의 합을 S(i,j) 라고 하자. 이 때 S(i,j) = S(j + 1) - S(i) 가 된다.


📎 참고자료

[알고리즘] 부분합, 누적합 쉽게 알아보기