본문 바로가기
Algorithm/알고리즘

[알고리즘] 접두사합(prefix sum) 알고리즘 by javascript (ft. 부분합/구간합)

by 썸머워즈 2022. 10. 12.
반응형

Prefix Sum(접두사 합)

부분합, 누적합, 구간합 등으로 불리며 해당 합을 빠르게 구하는 알고리즘이다.

사실 알고리즘 치고는 매우 간단하다.

 

이 알고리즘의 원리는 다음과 같다.

각각의 숫자까지의 합을 미리 계산하여 저장해놓고 그 저장한 값을 활용하여 구간합을 구한다.

 

사실 접두사합, 구간합, 부분합 알고리즘을 검색하면 많은 블로그가 나올 텐데, 

기본적으로 접두사 합 알고리즘의 공식을 다음과 같이 설명하고 있다.

P[Right] - P[Left - 1]

크게 틀린 공식은 아니니 일단 이런 식으로 사용하는구나 정도는 알고 진행하면 좋다.

 

다른 알고리즘도 마찬가지겠지만 문제에 따라 정해진 공식을 사용할 수 없는 경우가 많다.

예를 들어 숫자 [100, 101, 102, 103, 104]가 주어졌다고 가정한다면, 여기서 0번째부터 ~ 2번째까지의 합을 구하시오라고 한다면 위 공식을 그대로 사용할 수 있을까?

답은 아니요다.

 

위 공식은 첫 번째 인덱스 값이 0이 아닌 1이기 때문이다.

배열로 문제를 풀다 보면 첫 번째 인덱스를 0으로 지칭하는지, 1로 지칭하는지에 따라 유연한 사고가 필요하다.

 

뭐 아무튼 저 공식을 그대로 외울게 아니라 이 알고리즘의 원리가 어떤 식인지만 알고 문제에 따라 해결 방식을 다르게 하면 되는 게 전부이다.


예제 1) 특정 구간의 합을 담은 배열을 반환하라. (첫 번째가 0인 경우)

// numbers: [10, 20, 30, 40, 50, 60] (구간 합 대상 숫자 배열)
// S: [1, 2] (시작지점)
// F: [2, 4] (종료지점)
function solution(numbers, S, F) {
  let answer = [];
  const sums = [0];
  
  // 1. 구간합 미리 저장
  for (let i = 0; i < numbers.length; i++) {
    sums[i + 1] = sums[i] + numbers[i];
  }
  
  // 2. 구간합 구하기
  for (let i = 0; i < S.length; i++) {
    answer.push(sums[F[i] + 1] - sums[S[i]]);
  }
  return answer;
}

solution([10, 20, 30, 40, 50, 60], [1, 2], [2, 4]);
// [50, 120]

이 문제는 본문에서 설명했던 것처럼 첫 번째 숫자의 위치를 0번째로 지칭할 경우 이런 식으로 문제를 풀 수 있다.

[10, 20, 30, 40, 50, 60]에서 1번째부터 2번째까지 의 합은 50이 나오고, 2번째부터 4번째까지의 합은 120이 나온다.

예제 2) 특정 구간의 합을 담은 배열을 반환하라. (첫 번째가 1인 경우)

// numbers: [10, 20, 30, 40, 50, 60] (구간 합 대상 숫자 배열)
// S: [1, 2] (시작지점)
// F: [2, 4] (종료지점)
function solution(numbers, S, F) {
  let answer = [];
  const sums = [0];
  
  // 1. 구간합 미리 저장
  for (let i = 0; i < numbers.length; i++) {
    sums[i + 1] = sums[i] + numbers[i];
  }
  
  // 2. 구간합 구하기
  for (let i = 0; i < S.length; i++) {
    answer.push(sums[F[i]] - sums[S[i] - 1]);
  }
  return answer;
}

solution([10, 20, 30, 40, 50, 60], [1, 2], [2, 4]);
// [30, 90]

이게 본문에서 사용한 공식을 그대로 이용한 경우이다. 

구간합 구하기 부분만 조금 수정해서 사용하면 된다. 당연히 결과 값이 전혀 달라진다.

인덱스의 의미가 달라졌기 때문이다.

반응형


댓글

TOP