TaBo
개척하는 기록
TaBo
전체 방문자
오늘
어제
  • 기록들 (63)
    • Programming (35)
      • Java (19)
      • Servlet&Jsp (4)
      • Spring (4)
      • SpringBoot (1)
      • 기타 (2)
      • BOJ (5)
    • CS (16)
      • 자료구조 (4)
      • 알고리즘 (4)
      • 운영체제 (5)
      • 기본 용어 (3)
    • Project (4)
      • [Spring] 게시판 (4)
    • 나에 대한 기록 (8)

블로그 메뉴

  • Github

인기 글

태그

  • 운영체제
  • 스프링 게시판
  • Spring 게시판
  • c++
  • OS
  • 자바
  • java
  • 백준
  • 알고리즘
  • spring

최근 글

티스토리

hELLO · Designed By 정상우.
TaBo

개척하는 기록

[알고리즘/Java] 구간 합(Prefix Sum)과 관련 예제(BOJ-11659)
CS/알고리즘

[알고리즘/Java] 구간 합(Prefix Sum)과 관련 예제(BOJ-11659)

2022. 7. 20. 22:00

[ 1 ] 정수 배열 A에서 특정 구간(i ~ j) 내 모든 원소의 합을 구하라

특정 배열이 주어지고 위와 같은 질문을 받는다면, 우리는 어떻게 특정 구간 내 모든 원소의 합을 구할 수 있을까?

시간 제한이 없고 배열 원소의 수가 적다면 단순히 선형 탐색으로 i ~ j 까지의 특정 구간 내 원소의 합을 구할 수 있을 것이다.

하지만, 배열 내 원소의 수가 매우 많고, 계산해야 할 특정 구간도 많이 주어진다면 위와 같은 선형 탐색은 오랜 시간이 소요될 것이다.

 

[ 2 ] 구간 합(Prefix Sum)

[2 - 1] 정의

구간 합 알고리즘을 활용하면 선형 탐색으로 O(n)이 소요되던 시간 복잡도를 O(1)으로 줄일 수 있다. 어떻게 이것이 가능한가?

 

우선 A라는 정수 배열이 있을 때 S라는 '합 배열'을 정의해야 한다.

- S[i] = A[0] + A[1] + A[2] + A[3] + A[4] + ... + A[i-1] + A[i]

 

합 배열 S

 

합 배열 S[i]에는 배열 A의 0번째 인덱스 원소부터 i번째 인덱스 원소까지의 합에 대한 정보가 담겨있다. 즉, 합 배열을 미리 구해 놓음으로써 더 이상 선형 탐색을 할 필요가 없어지고 시간 복잡도가 O(1)으로 줄어드는 것이다.

 

 

[2- 2] 합 배열 S 만들기

합 배열 S는 다음과 같은 공식으로 만들 수 있다. 합을 저장하는 기본 정수 배열의 이름은 A라고 가정한다.

 

- S[i] = S[i-1] + A[i]

 

※ 매우 간단한 공식이지만, S[i-1]에 접근하므로 소스 코드로 구현할 때 반복문의 범위에 주의해야 한다.

 

 

[2 - 3] 특정 구간(i~j)의 구간 합을 구하기

배열 A의 i ~ j까지의 구간 내 원소의 합을 구하기 위해서는 다음과 같은 공식을 활용한다.

 

 S[ j ] - S[ i-1 ]

 

예시는 다음과 같다.

만약 위 그림에서 A[2] ~ A[4]까지의 합을 구한다고 가정하자.

S[4] = A[0] + A[1] + A[2] + A[3] + A[4] 이므로 S[4]에서 A[0] + A[1]을 빼면 A[2] ~ A[4]까지의 합이 나온다.

A[0] + A[1] = S[1] 이므로 결국 A[2] ~ A[4]까지의 합은 S[4] - S[1]이고,  S[ j ] - S[ i-1 ] 공식에 부합한다.

 

 

[ 3 ]  예제 - 백준 11659 Java 풀이

문제 출처: https://www.acmicpc.net/problem/11659

 

11659번: 구간 합 구하기 4

첫째 줄에 수의 개수 N과 합을 구해야 하는 횟수 M이 주어진다. 둘째 줄에는 N개의 수가 주어진다. 수는 1,000보다 작거나 같은 자연수이다. 셋째 줄부터 M개의 줄에는 합을 구해야 하는 구간 i와 j

www.acmicpc.net

[문제]

수 N개가 주어졌을 때, i번째 수부터 j번째 수까지 합을 구하는 프로그램을 작성하시오.

 

[입력]

첫째 줄에 수의 개수 N과 합을 구해야 하는 횟수 M이 주어진다. 둘째 줄에는 N개의 수가 주어진다. 수는 1,000보다 작거나 같은 자연수이다. 셋째 줄부터 M개의 줄에는 합을 구해야 하는 구간 i와 j가 주어진다.

 

[출력]

총 M개의 줄에 입력으로 주어진 i번째 수부터 j번째 수까지 합을 출력한다.

 

[풀이]

합 배열 S 만들기: S[i] = S[i-1] + A[i]

구간 합 구하기:  S[ j ] - S[ i-1 ]

 

위 공식을 활용하여 문제를 해결한다.

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
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());
		int M = Integer.parseInt(st.nextToken());
		
		long[] S = new long[N+1];
		
		st = new StringTokenizer(br.readLine());
		
		for(int i = 1; i <= N; i++)
		{
			S[i] = S[i-1] + Integer.parseInt(st.nextToken());
		}
		
		for(int j = 0; j < M; j++)
		{
			st = new StringTokenizer(br.readLine());
			int x = Integer.parseInt(st.nextToken());
			int y = Integer.parseInt(st.nextToken());
			System.out.println(S[y] - S[x-1]);
		}

	}

}

 

저작자표시 비영리 변경금지 (새창열림)

'CS > 알고리즘' 카테고리의 다른 글

[알고리즘/Java] 유니온 파인드(Union-Find)  (2) 2023.04.28
[알고리즘/Java] 슬라이딩 윈도우(Sliding Window)  (0) 2022.07.27
[알고리즘/Java] 투 포인터(Two Pointers)  (0) 2022.07.22
    'CS/알고리즘' 카테고리의 다른 글
    • [알고리즘/Java] 유니온 파인드(Union-Find)
    • [알고리즘/Java] 슬라이딩 윈도우(Sliding Window)
    • [알고리즘/Java] 투 포인터(Two Pointers)
    TaBo
    TaBo

    티스토리툴바