해당 코드는 먼제 답을 말하자면 투 포인터를 사용하여 풀었다.
원래 3중for문을 쓰는 괴상한(?) 구조로 만들어서 동작은 했지만 메모리 초과가 발생해서 투 포인터를 사용했다.
문제
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을 넘지 않는 자연수이다.
출력
투 포인터는 start와 end라는 시작점과 끝점 두가지 인덱스를 가리키는 변수를 이용해 배열검사를 컨트롤하는 방법이다.
중요한건 값의 합이 M을 넘었을 땐 더이상 더해줘서 검사할 필요가 없다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
int[] numArray = new int[N];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < N; i++) { //배열 초기화
numArray[i] = Integer.parseInt(st.nextToken());
}
//투포인터 사용
int cnt = 0; //M과 같은 경우의 수
int result = 0; //i ~ j 까지의 합 0으로 초기화
int start = 0; //시작 포인트
int end = 0; //끝 포인트
while (true) {
if (result >= M) { // 값이 목표 값보다 커지면 start번째 값을 빼고 시작포인트를 하나 오른쪽으로 옮긴다
result -= numArray[start];
start++;
} else if (end == N) { //값이 목표보다 크지 않고 끝 표인트가 N에 도달하면 종료
break;
} else { //end번째 값만큼 더해주고 끝 포인트 한칸 이동
result += numArray[end];
end++;
}
if (result == M) {
cnt++;
}
}
System.out.println(cnt);
}
}