숫자 배열이 주어진다.
이 때 A[i] + A[i+1] + ... + A[j] = M이 되는 (i,j) 쌍의 총 개수를 구하는 문제이다.
처음에는 쉽게 생각했다.
left= 0, right = 0으로 설정 후, ans = A[left]로 설정하였다.
이후 아래와 같은 상황으로 포인터를 움직였다.
ans > M : ans를 줄여야 할 필요가 있다. 따라서 구간을 줄여야 한다. 즉 left를 1증가시킨다
ans = M : 정답인 상황이다. left를 1증가시켜도 되고, right를 1 증가시켜도 되지만, 나는 right를 1 증가시켰다.(만약, A[x]가 0을 포함하고 있다면 상황이 복잡해지겠지만, 다행히도 A[x]는 자연수이다)
ans < M : ans를 키울 필요가 있다. 따라서 구간을 늘려야 한다. 즉 right를 1 증가시킨다.
문제는 아래의 조건에서 생겼다.
"만약 left = right인 경우는 어떻게 처리할 것인가?"
A[left] <= M일 경우는 그나마 다행이지만, 만약 A[right]>M일 경우 left를 1증가시키므로 left > right인 상황이 벌어진다.
따라서 이 부분을 처리해 줄 필요가 있었다.
먼저 ans에는 현재 A[left] 값이 저장되어 있을 것이다.
따라서, 먼저 ans = M인지를 확인하고, 만약 그럴 경우 경우의 수를 하나 더 해준다.
이후 right 포인터를 무조건 한칸 오른쪽으로 이동시킨 후 해당 값을 ans에 더해준다.
마지막으로 다음 반복문의 시행으로 건너 뛰어 right = left + 1인 상황에서 검사를 다시하는 방법으로 이 문제를 해결하였다.
이 때, right이 배열 범위를 벗어나더라도 left는 움직일 수 있지 않을까 생각할 수도 있을 것이다.
하지만, right이 배열의 범위를 넘어가는 경우는 총 2가지 경우이다.
A[left] + ... + A[right-1] <= M : A[left]가 빠지면 무조건 M 미만이 되므로 고려할 필요가 없다.
left = right & A[left] <=M : A[left]가 빠지면 구간이 존재하지 않으므로 구간합 또한 존재하지 않는다. 따라서 고려하지 않아도 된다.
위와 같은 이유로 따로 left를 추가적으로 움직여줄 필요는 없다.
import java.io.*;
import java.util.*;
public class Main {
static int N;
static long M;
static int[] arr;
static void two_pointer() {
int left = 0;
int right = 0;
long ans = arr[right];
long num = 0;
while(true) {
if(left==right) {
// left = right일 경우
// ans = M(즉, arr[left]=arr[right]=M)인지를 확인
// 이후, right = left + 1로 만들어준 뒤 다시 while문을 통해
// ans를 확인
if(ans==M) num++;
right++;
if(right >= N) break;
else {
ans += arr[right];
}
continue;
}
if(ans > M) {
// ans > M이여서 구간합을 줄여야 하는 경우
// left 포인터를 1증가시킨다.
ans -= arr[left];
left++;
}
else if(ans==M) {
num++;
right++;
if(right >= N) break;
else {
ans += arr[right];
}
}
else {
// ans < M이여서 구간합을 늘려야 하는 경우
// right 포인터를 이동시키는 모든 곳에서는
// 아래와 같은 로직을 사용해야 한다.
right++;
if(right >= N) break;
else {
ans += arr[right];
}
}
}
System.out.println(num);
}
public static void main(String[] args) {
FastReader sc = new FastReader();
N = sc.nextInt();
M = sc.nextLong();
arr = new int[N];
for(int i =0;i<N;i++) arr[i] = sc.nextInt();
two_pointer();
}
static class FastReader // 빠른 입력을 위한 클래스
}