hgk0404
hgk0404.tistory
hgk0404

공지사항

전체 방문자
오늘
어제
  • 전체 카테고리
    • [컴퓨터비전]
    • [Computer Science]
      • [컴퓨터네트워크]
      • [알고리즘]
      • [자료구조 in C]
      • [C & C++]
      • [이산수학]
      • [Math]
    • [머신러닝]
      • [Numpy, Pandas]
    • [Cloud]
      • [AWS]
      • [NCP]
      • [Kubernetes]
      • [Terraform]
    • [Dev]
      • [가상환경]
      • [Linux]
      • [Docker]
    • [Python]
    • [Coding Test]
      • [백준]
      • [프로그래머스]
      • [SQL]
    • [WEB]
    • [자격증, 일상]
    • [엑셀]
    • [금융]

인기 글

최근 글

최근 댓글

250x250
hELLO · Designed By 정상우.
hgk0404

hgk0404.tistory

[Computer Science]/[알고리즘]

[Algorithm] 누적 합(prefix sum) 알고리즘 by python

2022. 9. 21. 19:10
728x90

누적 합(prefix sum) 알고리즘이 있습니다.

 

배열의 일부 구간에 대해 아주 빠른 속도로 구해줄 수 있는 알고리즘입니다.

 

일반적으로 배열에서 일부분의 값을 구하기 위해선 O(N)의 시간이 소요되지만, 누적 합 알고리즘을 사용하면 O(1)의 시간 복잡도를 기대해 볼 수 있습니다.

 

누적 합 알고리즘을 구하는 2가지 방법이 있습니다.

 

1. 1차원 배열일 때

 

주어진 배열 arr와 누적합을 구할 0 * (arr의 길이 + 1)로 초기화된 배열 sum_arr가 있어야 합니다.

 

그리고 주어진 배열을 순차적으로 탐색하면서 sum_arr 배열을 완성시키면 됩니다.

 

누적합 배열이기 때문에 sum_arr[i]에는 arr[0] + arr[1] + ... + arr[i-1]까지의 수의 합이 들어가 있다고 생각해야 합니다.

 

예시)

arr = [ 2, 4, 1, -5, 2, -3 ]

 

sum_arr = [ 0, 2, 6, 7, 2, 4, 1 ]

 

sum_arr의 첫 번째 인덱스는 0으로 고정입니다. sum_arr[0]을 만족하는 arr[i]가 없기 때문입니다.

 

arr의 1번째와 4번째까지의 누적합을 구할 때 sum_arr를 이용할 수 있습니다.

 

공식은 다음과 같습니다.

sum[i, j] = sum_arr[j+1] - sum_arr[i]

 

 

공식에 적용하면 sum[1, 4] = sum_arr[4+1] - sum_arr[1]가 됩니다.

 

sum_arr[5] = 4이고 sum_arr[1]은 2이므로 4 - 2 = 2가 됩니다.

 

그리고 arr = [ 2, 4, 1, -5, 2, -3 ]에서 1번째와 4번째 구간의 누적합은 2 + 4 + 1 + (-5) = 2입니다. 

 

둘의 값이 2로 동일합니다.

 

코드로 구현하면 다음과 같습니다.

for i in range(n):
    tmp += number[i]
    sum_number[i+1] = tmp

 

sum_arr[i]를 for문으로 누적합을 구해줍니다.

a, b = input().split() # 원하는 구간이 정수로 주어졌을때
print(sum_arr[b-1+1] - sum_arr[a-1]) # 인덱스가 0부터 시작하기 때문에 -1

 

2. 2차원 배열일 때

 

 

1차원 배열일 때 sum_arr의 길이가 n+1이 되었듯이 2차원 배열일때는 arr가 N X N이라면 sum_arr도 (N+1) X (M+1)이 됩니다. 

 

이때 sum_arr의 각항은 arr[0][0]부터 arr[i-1][j-1]까지의 각 항의 합이 됩니다. 

 

그림으로 알아보겠습니다.(클릭하면 출처로 이동합니다.)

 

그림에 따라 sum_arr[3][3]는 arr[0][0]부터 arr[2][2]까지의 누적합이 됩니다.

 

2차원 배열에서의 누적합을 구하는 공식은 다음과 같습니다.

sum_arr[i][j] = arr[i-1][j-1] + sum_arr[i-1][j] + sum_arr[i][j-1] - sum_arr[i-1][j-1]

 

2중 for문을 사용하여 sum_arr를 구해줄 수 있습니다.

arr = [[ 1, 2, 3, 4 ],
       [ 2, 3, 4, 5 ],
       [ 3, 4, 5, 6 ],         
       [ 4, 5, 6, 7 ]]
n = 4 # 정방형 행렬
sum_arr = [ [0] * (n+1) for _ in range(n+1) ]
for i in range(1, n+1):
    for j in range(1, n+1):
        sum_arr[i][j] = arr[i-1][j-1] + sum_arr[i-1][j] + sum_arr[i][j-1] - sum_arr[i-1][j-1]

for i in range(n+1):
    print(*sum_arr[i])

 

결과)

0 0 0 0 0
0 1 3 6 10
0 3 8 15 24
0 6 15 27 42
0 10 24 42 64

 

2차원 sum_arr를 구했으니 이제 특정 구간에서의 합을 구하는법을 알아보겠습니다.

 

arr의 (x1, y1)부터 (x2, y2)까지의 합을 sum이라고 할때

 

공식은 다음과 같습니다.

sum = sum_arr[x2+1][y2+1] - sum_arr[x1][y2+1] - sum_arr[x2+1][y1] + sum_arr[x1][y1]

 

arr(1, 1)부터 arr(3, 2)까지 더하기

sum = sum_arr[4][3] - sum_arr[1][3] - sum_arr[4][1] + sum_arr[1][1]
# 42 - 6 - 10 + 1 = 27

 

 

 


참고1

그림 출처

2차원 배열 누적합 문제

 

 

728x90
저작자표시 동일조건 (새창열림)

'[Computer Science] > [알고리즘]' 카테고리의 다른 글

[Algorithm] 가장 긴 증가하는 부분 수열(longest increasing subsequence)  (0) 2022.08.18
[Algorithm] monotone stack 알고리즘  (0) 2022.07.23
[Algorithm] BackTracking(백트래킹) 알고리즘  (0) 2022.07.16
[Algorithm] 다이나믹 프로그래밍(DP) - 탑다운, 바텀업  (0) 2022.07.14
[Algorithm] 다익스트라 알고리즘  (0) 2022.07.11
'[Computer Science]/[알고리즘]' 카테고리의 다른 글
  • [Algorithm] 가장 긴 증가하는 부분 수열(longest increasing subsequence)
  • [Algorithm] monotone stack 알고리즘
  • [Algorithm] BackTracking(백트래킹) 알고리즘
  • [Algorithm] 다이나믹 프로그래밍(DP) - 탑다운, 바텀업
hgk0404
hgk0404
공부기록

티스토리툴바