문제링크
https://www.acmicpc.net/problem/2003
2003번: 수들의 합 2
첫째 줄에 N(1 ≤ N ≤ 10,000), M(1 ≤ M ≤ 300,000,000)이 주어진다. 다음 줄에는 A[1], A[2], …, A[N]이 공백으로 분리되어 주어진다. 각각의 A[x]는 30,000을 넘지 않는 자연수이다.
www.acmicpc.net
문제설명
문제
N개의 수로 된 수열 A[1], A[2], …, A[N] 이 있다. 이 수열의 i번째 수부터 j번째 수까지의 합 A[i] + A[i+1] + … + A[j-1] + A[j]가 M이 되는 경우의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N(1 ≤ N ≤ 10,000), M(1 ≤ M ≤ 300,000,000)이 주어진다. 다음 줄에는 A[1], A[2], …, A[N]이 공백으로 분리되어 주어진다. 각각의 A[x]는 30,000을 넘지 않는 자연수이다.
출력
첫째 줄에 경우의 수를 출력한다.
예제 입력 1 복사
4 2
1 1 1 1
예제 출력 1 복사
3
예제 입력 2 복사
10 5
1 2 3 4 2 5 3 1 1 2
예제 출력 2 복사
3
문제풀이
보자마자 투포인터로 풀면 되겠다고 생각했다.
하지만 오랜만에 접한 탓인지,
순간 i, j의 값이 같을때와 다를때를 구분해서 풀려고했다.
하지만 이문제는 i~j까지의 합을 알면 되는 문제이므로 같을때를 따로 분리해서 로직을 실행할 필요가 없다.
핵심
포인터 변수 2개로 리스트 전체를 탐색하며 구간합과 M값을 비교
1. 구간합 구하기 => ★인덱스 슬라이싱, sum() 활용
구간을 for in range()로 정하여 돌렸더니 보기좋게 시간초과가 났다.
내부적으로 최적화된 메서드들 잘 활용하자...
2. 구간합 < M : j값 1 증가 (우측 포인터 이동 / 구간합 늘리기 위해)
구간합 > M : i값 1 증가 (좌측 포인터 이동 / 구간합 감소 위해)
구간합 == M : cnt 증가 및 j값 1증가 (우측 포인터 이동)
cf. 투포인터 알고리즘 시간복잡도는 최악의 경우에도 O(N)이다.
두개의 포인터가 항상 l <=r 로 움직이기 때문에 두 포인터가 증가하는 과정은 최대 N번만 반복될 것이다.
코드
N, M = map(int,input().split())
A = list(map(int, input().split()))
i = 0
j = 0
cnt = 0
while i < N and j < N:
# A[i]와 A[j]합을 구해 M보다 작으면 j값 증가, 크면 i값증가, 같으면 cnt += 1
testSum = sum(A[i:j+1])
if testSum < M:
j += 1
elif testSum > M:
i += 1
else:
cnt += 1
j += 1
print(cnt)
'알고리즘 > 백준' 카테고리의 다른 글
[백준 2230] 수 고르기 (with Python / 투포인터) (0) | 2023.08.26 |
---|---|
[백준 2531] 회전초밥 (with Python / 투포인터) (0) | 2023.08.25 |
[백준 1012] 유기농 배추 (with Python / BFS) (1) | 2023.08.24 |
[백준 7562] 나이트의 이동 (with Python / BFS) (0) | 2023.08.24 |
[백준 10026] 적록색약 (with Python / BFS) (0) | 2023.08.23 |