[백준 Java] 2143번 두 배열의 합

2024. 1. 13. 02:31·Algorithm/PS - 백준
728x90
반응형

💡문제

[Gold III] 두 배열의 합 - 2143

문제 링크

성능 요약

메모리: 112696 KB, 시간: 556 ms

깨진 부분은 여기에서 확인


🤔접근법

범위 체크 및 시간복잡도 예상

  • -1,000,000,000 ≤ T ≤ 1,000,000,000 (십억)
  • 1 ≤ n ≤ 1,000, 1 ≤ m ≤ 1,000
  • 배열 원소는 절댓값이 1,000,000을 넘지 않는 정수
  • $O(\sqrt T)$ 또는 $O(n^2)$이하 이어야 한다.

풀이법

❌ 접근 방법. 완탐

  1. 배열 A의 가능한 부분 배열 만들기 → $O(N^2)$
  2. 배열 B의 부분합이 T-(배열 A의 부분합)인 모든 부 배열 찾기 → $O(N^2)$

➡️ 해당 풀이법의 시간 복잡도 : $O(N^4)$

당연히 시간복잡도 초과


⭕ 접근 방법. Map을 이용해 누적합 저장하여 빠르게 조회

👇 Map을 이용해 배열의 누적합을 빠르게 조회하는 것은 아래 문제를 리뷰하며 자세히 기록해 두었다.
2015번 수들의 합 4

Map에 저장 해야 할 것은 key : 부분합으로 나올 수 있는 값 , value : 부분합을 key로 가지는 부분배열의 개수

Map을 통해 저장하면 누적합으로 같은 값을 가지는 배열의 개수를 알아낼 수 있다.

  1. 배열 A와 배열 B에서 만들 수 있는 부분합 모두 구하기 → $O(N^3)$
    1-1. 1 ~ n까지 순회하며 배열의 누적합($S_n$)을 구한다. → $O(N)$
    1-2. 배열에서 $S_j$(j번째의 누적합)을 구하고 있다면 i ≤ j 조건을 만족하는 $S_j - Si$ 부분합을 모두 구한다. → $O(N^2)$
    1-3. 부분합을 key로 가지는 map이 존재하면 value에 +1, 존재하지 않는다면 map에 추가
  2. 배열 A의 map의 key를 순회하며 T - (배열A의 부분합) 값을 배열 B의 map에 key로 존재하는지 확인
    → $O(N^2)$ 최대 부분합의 개수는 N*N이기 때문에 key를 순회하는게 N*N이다.
    2-1. 존재한다면 배열 A의 map의 value * 배열 B의 map의 value

➡️ 해당 풀이법의 시간 복잡도 : $O(N^3)$
스터디 →1000^3 는 십억인데 어떻게 통과하는지 이야기해보기.


😎SUCCESS


👩‍💻 코드

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

public class Main_2143 {
    static long T;  // 목표 합
    static int n;   // 배열 A의 크기
    static int m;   // 배열 B의 크기
    static long sumA[]; // 배열 A의 누적합
    static long sumB[]; // 배열 B의 누적합
    static HashMap<Long, Long> mapA; // 배열 A의 부분합과 그 등장 횟수를 저장하는 맵
    static HashMap<Long, Long> mapB; // 배열 B의 부분합과 그 등장 횟수를 저장하는 맵
    static long cnt; // 결과로 출력할 쌍의 개수

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        T = Long.parseLong(br.readLine());

        n = Integer.parseInt(br.readLine());

        // 배열 A에서 누적합 구하면서 가능한 부분합의 개수 구하기
        sumA = new long[n + 1];
        mapA = new HashMap<>();
        StringTokenizer st = new StringTokenizer(br.readLine());
        for (int j = 1; j <= n; j++) {
            sumA[j] = sumA[j - 1] + Long.parseLong(st.nextToken());

            for (int i = 0; i < j; i++) {
                // 배열 A에서 i~j의 부분합을 키로 가지는 맵이 있다면 그 값을 반환해서 +1하고
                // 없다면 0(default)를 반환해서 +1 해라.
                mapA.put(sumA[j] - sumA[i], mapA.getOrDefault(sumA[j] - sumA[i], 0L) + 1);
            }
        }

        // 배열 B에서 누적합 구하면서 가능한 부분합의 개수 구하기
        m = Integer.parseInt(br.readLine());
        sumB = new long[m + 1];
        mapB = new HashMap<>();
        st = new StringTokenizer(br.readLine());
        for (int j = 1; j <= m; j++) {
            sumB[j] = sumB[j - 1] + Long.parseLong(st.nextToken());

            for (int i = 0; i < j; i++) {
                // 배열 B에서 i~j의 부분합을 키로 가지는 맵이 있다면 그 값을 반환해서 +1하고
                // 없다면 0(default)를 반환해서 +1 해라.
                mapB.put(sumB[j] - sumB[i], mapB.getOrDefault(sumB[j] - sumB[i], 0L) + 1);
            }
        }

        // mapA의 키 순회
        for (long key : mapA.keySet()) {
            // mapB에 T - (map의 key(부분합))을 key로 가진다면
            if (mapB.containsKey(T - key)) {
                // 해당 부분합이 몇 번 등장하는지를 계산하고 cnt에 더해준다.
                cnt += mapA.get(key) * mapB.get(T - key);
            }
        }

        // 결과 출력
        System.out.println(cnt);
    }
}
반응형

'Algorithm > PS - 백준' 카테고리의 다른 글

[백준 Java] 1407번 2로 몇 번 나누어질까  (0) 2025.03.23
[백준 Java] 3020번 개똥벌레  (0) 2024.01.13
[백준 Java] 2015번 수들의 합 4  (0) 2024.01.12
[백준 Java] 2004번 조합 0의 개수(정수론)  (0) 2024.01.09
[백준 Java] 2247번 실질적 약수(정수론)  (1) 2024.01.08
'Algorithm/PS - 백준' 카테고리의 다른 글
  • [백준 Java] 1407번 2로 몇 번 나누어질까
  • [백준 Java] 3020번 개똥벌레
  • [백준 Java] 2015번 수들의 합 4
  • [백준 Java] 2004번 조합 0의 개수(정수론)
제가안난데여♪(´ε`*)
제가안난데여♪(´ε`*)
기억의 유한함을 기록의 무한함으로 ✍️ 예비 개발자가 꿈꾸는 공간 여기는 안나의 개발 블로그 💻
  • 제가안난데여♪(´ε`*)
    안나의 전두엽 어딘가 🧠
    제가안난데여♪(´ε`*)
    기억의 유한함을 기록의 무한함으로 ✍️ 예비 개발자가 꿈꾸는 공간 여기는 안나의 개발 블로그 💻
  • 전체
    오늘
    어제
    • 분류 전체보기 (128)
      • 간단하게 한스푼🥄 (1)
      • Programming (56)
        • Spring (16)
        • Vue.js (6)
        • Deep Learning (3)
        • DataBase (5)
        • React (26)
      • DevOps (21)
        • Docker (12)
        • Linux (4)
      • Algorithm (46)
        • 알고리즘 정리 (5)
        • 자료구조 (0)
        • PS - 백준 (28)
        • 99클럽 코테 스터디 (13)
      • Project (0)
        • CampFire (0)
      • 안나의 취뽀일기 (˵ •̀ ᴗ - ˵ ) ✧ (4)
        • SSAFY_9기 (2)
        • SW 부트캠프 (2)
  • 잔디 달력

    «   2025/06   »
    일 월 화 수 목 금 토
    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
  • 인기 글

  • 태그

    백준
    Vue.js 입문하기
    자바
    개발자 취업
    알고리즘
    리액트 상태
    java 백준
    java
    til
    stack
    99클럽
    linux
    도커컨테이너
    코딩테스트 준비
    항해99
    도커
    springboot
    Vue
    백준 java
    Vue.js
    docker
    java stack
    백준 구현문제
    greedy
    React
    front-end
    김영한
    Spring
    topology sort
    자바 스택
  • 06-16 12:32
    반응형
  • hELLO· Designed By정상우.v4.10.3
제가안난데여♪(´ε`*)
[백준 Java] 2143번 두 배열의 합
상단으로

티스토리툴바