• Home
  • About
    • Che1's Blog photo

      Che1's Blog

      Che1's Dev Blog

    • Learn More
    • Facebook
    • Instagram
    • Github
    • Steam
    • Youtube
  • Posts
    • All Posts
    • Django
    • Python
    • Front-end
    • Algorithm
    • etc
    • All Tags
  • Projects

[Codility] Lv5 - Prefix Sums

11 Apr 2018

Reading time ~2 minutes

어떤 정수들의 배열이 주어졌을 때 그 배열의 연속된 일부의 총 합을 매우 빠르게 구할 수 있는 방법을 배웠다. 바로 Prefix Sums 를 사용하는 방법이다.


Prefix Sums

Prefix Sums 란 어떤 정수 배열 내 요소들의 각 index 까지의 총 합을 저장해놓은 별도의 배열을 말한다.

예를 들어서 아래와 같은 배열 a가 있을 때,

a = [1, 2, 3, 4, 5, 6]

이 배열의 Prefix Sums 배열 P는 다음과 같다.

P = [0, 1, 3, 6, 10, 15, 21]

이는 아래와 같은 계산을 통해 구해진다.

P[0] = 0
P[1] = a[0]
P[2] = a[0] + a[1]
P[3] = a[0] + a[1] + a[2]
P[4] = a[0] + a[1] + a[2] + a[3]
.
.
.

이걸 다시 쓰면 다음과 같이 된다.

P[0] = 0
P[1] = P[0] + a[0]
P[2] = P[1] + a[1]
P[3] = P[2] + a[2]
.
.
.
P[k] = P[k - 1] + a[k - 1]

Prefix Sums 의 계산을 함수로 작성하면 다음과 같다.

def prefix_sums(A):
    n = len(A)
    P = [0] * (n + 1)
    for k in range(1, n + 1):
        P[k] = P[k - 1] + A[k - 1]
    return P

Prefix Sums 활용하기

이 Prefix Sums 를 활용하면 다음과 같은 배열의 슬라이스들의 총 합을 매우 빠르게 구할 수 있다.

[1, 2, 3]
[2, 3, 4]
[3, 4, 5, 6]
.
.
.

각각의 슬라이스들의 총 합을 구하는 가장 심플한 방법은 각 슬라이스들을 순회하면서 각 요소들을 더해주면 된다.

sum([1, 2, 3])
sum([2, 3, 4])
sum([3, 4, 5, 6])
.
.
.

만약에 위와 같은 슬라이스 m 개의 각각의 총 합을 구해야한다고 생각해보자. 이때 가장 간단한 접근방법으로 계산한다면 최악의 경우 \( O(nm) \) 시간이 걸린다.
하지만 Prefix Sums 를 활용하면 \( O(n+m) \) 시간만에 해낼 수 있다.

a[0:2] 인 슬라이스 [1, 2, 3] 의 총 합을 Prefix Sums 를 이용해서 구해보자.
Prefix Sums P는 아래와 같다.

P = [0, 1, 3, 6, 10, 15, 21]

a[0]에서 a[2] 까지의 총 합은 P[3] 이므로 P[3] 은 sum([1, 2, 3]) 과 같다. 하지만 실행시간은 \( O(1) \) 으로 훨씬 빠르다.

a[2:5] 인 슬라이스 [3, 4, 5] 의 총 합은 어떻게 구할까?

생각을 해보면 [3, 4, 5] 의 총 합은 [1, 2, 3, 4, 5] 의 총 합에서 [1, 2] 의 총 합을 뺀 값이다. 각각의 값을 P에서 찾아서 계산해주면 된다.

[1, 2, 3, 4, 5] 의 총 합은 P[5], [1, 2] 의 총 합은 P[2] 이다. 따라서 P[5] - P[2] 를 해주면 [3, 4, 5] 의 총 합을 구할 수 있다.

일반화하면 a[x:y] 의 총 합은 P[y] - P[x] 와 같다.

이것을 함수로 정의하면 아래와 같다.

def count_total(P, x, y):
    return P[y] - P[x]

이를 활용해 m 개의 슬라이스들의 합을 구하면 \( O(n+m) \) 시간만에 해낼 수 있다.


Reference

Codility



AlgorithmCodilityPrefix Sums Share Tweet +1