어떠한 자연수 N은, 몇 개의 연속된 자연수의 합으로 나타낼 수 있다. 당신은 어떤 자연수 N(1 ≤ N ≤ 10,000,000)에 대해서, 이 N을 몇 개의 연속된 자연수의 합으로 나타내는 가지수를 알고 싶어한다. 이때, 사용하는 자연수는 N이하여야 한다.
예를 들어, 15를 나타내는 방법은 15, 7+8, 4+5+6, 1+2+3+4+5의 4가지가 있다. 반면에 10을 나타내는 방법은 10, 1+2+3+4의 2가지가 있다.
N을 입력받아 가지수를 출력하는 프로그램을 작성하시오.
첫 줄에 정수 N이 주어진다.
입력된 자연수 N을 몇 개의 연속된 자연수의 합으로 나타내는 가지수를 출력하시오

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
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());
//N : 입력 받을 수의 갯수
int N = Integer.parseInt(st.nextToken());
//예시의 경우, 15처럼 연속된 수가 아닌 하나의 수로도 합을 나타낼수 있기때문에 미리 1세팅
int count = 1;
//start와 end가 1로 시작하므로, sum도 1로 초기값 세팅
int sum = 1;
int start = 1;
int end = 1;
//end가 N이 아닐때까지 출력
// (end가 N일때는 마지막 값에서 하나의 수로도 합을 나타낼 수 있기 때문에-> 이 경우는 이미 count = 1로 미리 세팅해둠)
while (end != N){
//sum과 n이 같으면 count ++, end 한칸 뒤로 옮긴 후 그값을 sum에 더해줌
if(sum==N){
count++;
end ++;
sum = sum + end;
//sum이 N보다 크면 sum에서 start를 빼주고, start 한칸 뒤로 옮김
}else if (sum > N){
sum = sum - start;
start++;
//sum이 N보다 작으면 end를 한칸 뒤로 옮기고, sum에 end를 더함
}else {
end++;
sum=sum+end;
}
}
System.out.println(count);
}
}
말그대로 포인터 두개를 가지는 방식이다.
위 문제와 같이 특정한 합을 가지는 부분 연속 수열 찾기 문제에서 주로 사용된다.


[start, end] → [start, end+1]로 확장하는 것이기 때문에 end를 먼저 증가 시킨 후 누적합을 갱신하는게 맞다.

[start, end] → [start+1, end] 로 감소시키는 것 이기 때문에 sum에서 먼저 start_index를 빼는 것이 맞다.위의 풀이처럼 코드를 짜면 된다! 이해만 한다면 쉽다.