어떠한 자연수 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을 입력받아 가지수를 출력하는 프로그램을 작성하시오.
백준 2018 상세보기
연속된 자연수의 합이 N이 되는 경우의 수를 구하는 문제이다. 이런 경우 투 포인터 알고리즘을 활용할 수 있다.
작성할 코드를 단계별로 생각해 보자.
start = 1, end = 1, sum = 1, count = 1
📌 투 포인터 이동 방법
start를 오른쪽으로 한 칸 이동하는 것은 연속된 자연수에서 작은 값을 빼는 것과 같고, end를 오른쪽으로 한 칸 이동하는 것은 연속된 자연수의 범위를 한 칸 더 확장하여 더 큰 값을 만들기 위함이다.연속된 자연수의 합이 N과 같을 때는 경우의 수를 증가시키고, end를 오른쪽으로 이동시킨다.
sum < N 일 경우 : 종료 인덱스 증가(end++), sum 값 변경(sum += end)
sum = N 일 경우 : count 증가, 종료 인덱스 증가(end ++), sum 값 변경(sum += end)
sum > N 일 경우 : sum 값 변경(sum -= start), 시작 인덱스 증가(start++)
start = 1, end = 1, sum = 1
start = 1, end = 2, sum = 3
start = 1, end = 5, sum = 15
start = 1, end = 6, sum = 21
start = 2, end = 6, sum = 2
위의 과정을 end 인덱스가 N이 될 때가지 반복하여, 결과 값 count를 출력한다.
import java.util.*;
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int start = 1; // 시작 포인터
int end = 1; // 종료 포인터
int sum = 1; // 연속된 자연수의 합
int count = 1; // 연속된 자연수의 합이 N과 같은 경우의 수
while(end != N) {
if(sum < N) {
end++;
sum += end;
} else if(sum > N) {
sum -= start;
start ++;
} else { // sum == N
count++;
end++;
sum += end;
}
}
System.out.println(count);
}
}
백준 2018 문제를 통해 투 포인터의 기본적인 동작 과정을 학습하였다. 투 포인터는 2개의 포인터를 이동시키면서 연산을 진행하여 시간 복잡도를 최적화한다. 이때, 문제마다 두 개의 포인터의 시작 위치와 연산 과정은 다를 수 있으므로 다양한 문제를 풀어보면서 투 포인터 알고리즘을 활용하는 능력을 키워보면 좋을 것 같다.😎