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

(1)자료구조 ② 구간합

by 사라리24 2024. 4. 9.
SMALL

1. 구간 합 구하기1

 

 

 

  • 문제
 
    
 
      Q. 수 N개가 주어졌을 때 i번째 수에서 j번째 수까지의 합을 구하는 프로그램을 작성하시오.


 
[입력] [출력]
1번째 줄에 숫자의 개수 N (1≤N ≤100,000)
합을 구해야 하는 횟수 (1≤M ≤100,000)
총 M개의 줄에 입력으로 주어진
i번째 수에서 j번째 수까지의 합을 출력한다.
2번째 줄에 N개 수가 주어진다.
(각 수는 1,000보다 작거나 같은 자연수다.)
3번째 줄부터는 M개의 줄에
합을 구해야 하는 구간 i와 j가 주어진다.

 

 

  • 풀이방법
 
1. N개의 수를 입력받은 동시에 합배열 생성

    * 합배열 >>>> S[i] = S[i-1] + A[i]

2. i~j 가 주어지면 구간합을 구하는 공식으로 정답 출력

    * 구간합 >>> S[j] - S[i-1]

 

 

  • 코드 순서
 
1. suNo(숫자 개수), quizNo(질의 개수)

2. numbers 변수에 숫자 데이터 저장

3. prefix_sum 합배열 변수 선언

4. temp 변수 선언

5. for 저장한 숫자 데이터 차례대로 탐색:
    temp에 현재 숫자 데이터 더해 주기
    합 배열에 temp값 저장

6. for 질의 개수만큼 반복:
    질의 범위 받기 (s ~ e )
    구간 합 출력하기 (prefix_sum[e] - prefix_sum[s-1])

 

 

  • 정답
             


              suNo
,quizNo = map(int, input().split())

              numbers = list(map(int, input().split()))

              prifix_sum = [0]

              temp = 0


              for i in numbers:

                  temp = temp + i

                  prifix_sum.append(temp) 


              for i in range(quizNo):

                  s, e = map(int, input().split())

                  print(prifix_sum[e]-prifix_sum[s-1]) 



[입력] [출력]

5 3

5 4 3 2 1

1 3

2 4

5 5

12

9

1

 

  • 다른 답


     n
, m = map(int, input().split())
      array = list(map(int, input().split()))

      newarray = []
      sum = 0

      for i in array:                      # 합배열 구하기
          sum += i
          newarray.append(sum)

      for i in range(m):
          x, y = map(int, input().split())

          if x == 1:
              print(newarray[y - 1])            
             
# x가 1이면 기본 배열에서 배열의 0번째 인덱스부터 더해주는 것.
            즉, 합배열에서는 제외하고 마지막부분만 보면 된다.

          else:
            print(newarray[y - 1] - newarray[x - 2])


 

 

 

2. 구간합 구하기2

 

 

 

  • 문제

 


      Q. N x N개의 수가 N x N 크기의 표에 채워져 있다. 표 안의 수 중 
(X₁,Y₁)에서 (X₂,Y₂)까지의 합을 구하려 한다.
         X는 행, Y는 열을 의미한다. 예를 들어 N = 4이고, 표가 다음과 같이 채워져 있을 때를 살펴보자.
         (2,2)에서 (3,4)까지의 합을 구하면 3+4+5+4+5+6=27 이고, (4,4)에서 (4,4)까지의 합을 구하면 7이다.
         표에 채워져 있는 수와 합을 구하는 연산이 주어졌을 때 이를 처리하는 프로그램을 작성하시오.


 
[입력] [출력]
1번째 줄에 표의 크기 N (1 ≤ N ≤ 1024)
합을 구해야 하는 횟수 M ( 1 ≤  M ≤ 100,000)
총 M 줄에 걸쳐 (X₁, Y₁) 에서 (X₂, Y ₂)의 합을 구해 출력
2번째 줄부터 N개의 줄에는 표에 채워야 하는 수가 1행부터 차례대로 주어집니다.
다음 M 개의 줄에는 4개의 정수 X₁, Y, X₂, Y ₂ 가 주어집니다.

@ 표에 채워져 있는 수는 1,000보다 작거나 같은 자연수
( X₁   X₂ , YY ₂)

 



  • 풀이방법
 
1. 2차원 구간 합 배역의 1행, 1열부터 구합니다. 구간 합 배열 1행, 1열은 다음과 같이 구합니다.



- 행 구하기: D [ 1 ] [ j ] = D [ 1 ] [ j - 1 ] + A [ 1 ] [ j ]
- 열 구하기: D [ i ] [ 1 ] = D [ i - 1 ] [ 1 ] + A [ i ] [ 1 ]

2. 합배열 채우기

D [ i ] [ j ] = D [ i ] [ j - 1 ] + D [ i -1 ] [ j ] - D [ i - 1 ] [ j - 1 ] + A [ i ] [ j ]

3. X₁, Y, X₂, Y ₂ 에 대한 답 구하기

D [ X₂ ] [ Y ₂ ] -  D [ X₁ - 1 ] [ Y ₂] - D [ X₂ ] [ Y ₁ - 1 ] + D [  X₁ - 1 ] [ Y ₁ - 1 ]

 

 

  • 코드 순서
 
1. n (리스트 크기), m (질의 수), A (원본 리스트), D (합 배열) 정의

2. for n 만큼 반복:
    원본 리스트 데이터 저장

3. for i를 1부터 n까지 반복:
       for j를 1부터 n까지 반복:
           합배열 저장
            D [ i ] [ j ] = D [ i ] [ j - 1 ] + D [ i -1 ] [ j ] - D [ i - 1 ] [ j - 1 ] + A [ i ] [ j ]

4. for m만큼 반복:
       질의에 대한 결과 계산 및 출력
       결과 = D [ X₂ ] [ Y ₂ ] -  D [ X₁ - 1 ] [ Y ₂] - D [ X₂ ] [ Y ₁ - 1 ] + D [  X₁ - 1 ] [ Y ₁ - 1 ]

 

  • 정답



      n
, m = map(int, input().split())
       A = [[0] * (n+1)]
       D = [[0] * (n+1) for _ in range(n+1)]

       for i in range(n):
           A_row = [0] + [int(x) for x in input().split()]
           A.append(A_row)

       for i in range(1,n+1):
           for j in range(1,n+1):
               #구간 합 구하기
               D[i][j] = D[i][j - 1] + D[i - 1][j] - D[i - 1][j - 1] + A[i][j]

       for _ in range(m):
           x1, y1, x2, y2 = map(int, input().split())
 
           result = D[x2][y2] - D[x1-1][y2] - D[x2][y1-1] + D[x1-1][y1 -1]
           print(result)


[입력] [출력]
4 3
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
2 2 3 4
3 4 3 4
1 4 1 4
27

6

64
2 4
1 2
3 4
1 1 1 1
1 2 1 2
2 1 2 1
2 2 2 2
1

2

3

4

 

 

 

3. 나머지 합 구하기

 

  • 문제


      Q. N개의 수 A₁, A₂,...An 이 주어졌을 때 연속된 부분의 합이
          M으로 떨어지는 구간의 개수를 구하는 프로그램을 작성하시오.
          즉, Ai, A₂,...Aj(i≤j)의 합이 M으로 나누어떨어지는 (i,j) 쌍의 개수를 구하시오.


[입력] [출력]
1번째 줄에 N과 M 
( 1 ≤ N   10⁶ ) ( 2 ≤ M   10³ ) 
1번째 줄에 연속된 부분의 합이 M으로 나누어떨어지는 구간의 개수를 출력
2번째 줄에 N개의 수 A₁, A₂,...An 이 주어진다.
 (0 ≤ Ai  ≤ 10⁹)

 

  •  풀이방법
 
1. 리스트 A와 합 배열 S 를 생성한다.




2. 합배열 S 의 모든 값을 M으로 나눈 나머지 연산을 수행해 값을 업데이트하기




3. 나머지가 같은 개수끼리 경우의 수 따져 결과값에 추가하기

          ₃C₂ => 3
          ₂C₂ => 1


4. 모든 경우의 수 세기


           3 + 3  + 1 = 7


 

 

  • 코드 순서
 
1. n (수열의 개수), m(나누어 떨어져야하는 수), A (원본수열) , S(합 배열), C(인덱스 카운트 리스트), answer 선언하기

2. for i -> 1 ~ n-1:
        S[i] = S[i-1] + A[i]

3. for i -> 0 ~ n-1:
         remainder = S[i] % M
         if ( remainder == 0 ) 정답 +1
         C[remainder]의 값을 1 증가

4. for i -> 0 ~ m-1:
         C[i](i가 나머지인 인덱스의 개수)에서 2가지를 뽑는 경우의 수를 정답에 더하기

5. 결과값 출력

 

  • 정답

      n
, m = map(int, input().split())
      A = list(map(int, input().split()))
      S = [0]*n
      C = [0]*m
      S[0] = A[0]
      answer = 0

      for i in range(1, n):
           S[i] = S[i-1] + A[i]  

      for i in range(n):
          remainder = int(S[i] % m) 
          if remainder == 0:  
             answer += 1
          C[remainder] += 1   

      for i in range(m):
          if C[i] > 1:
            answer += (C[i] * (C[i] - 1) / 2)

      print(int(answer))


[입력] [출력]

5 3

1 2 3 1 2

7

 

  • 다른 답



        n
,m = map(int, input().split())
         a = list(map(int, input().split()))

         count= [0]*m
         count[0] = 1
         result =0
         sum_mod_m =0

         for num in a:
             sum_mod_m = (sum_mod_m +num) % m
             result += count[sum_mod_m]
             count[sum_mod_m]+=1

         print(result)



 

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

(1)자료구조 ④ 슬라이딩 윈도우  (0) 2024.04.11
(1)자료구조 ③ 투 포인터  (1) 2024.04.10
(1)자료구조 ① 배열과 리스트  (0) 2024.04.09