제한시간 2초 = 2억번의 연산안에 끝나야한다.
의 최댓값 = 10,000,000
= 10,000,000 -> = 약 230,000,000 (2억3천)
위 시간복잡도는 제한시간을 넘어가므로 위 시간복잡도보다 좀 더 작은 시간복잡도를 사용해야한다. or or
의 시간복잡도를 가진 투 포인터를 사용해보자
위 이미지는 투포인터를 이용해 12(N) 를 연속된 자연수의 합으로 나타내는 가지수를 구하는 과정을 보여준다.
어떠한 이동법칙이 보일것이다. (이미지 안에 적어 두었다ㅎ)
N > sum(연속된 자연수의 합)
end_index++;
sum += end_index;
N < sum
sum -= start_index;
start_index++;
N == sum
end_index++;
sum += end_index;
long N = 입력 받기
사용 변수들 초기화(long count, startIdx, endIdx, sum;)
while(endIdx != N) {
if(sum == N){
count 증가
endIdx 증가
sum 변경
}else if(sum > N) {
sum 변경
startIdx 증가
}else if(sum < N) {
endIdx 증가
sum 변경
}
}
count 출력
위 처럼 슈도 코드를 작성하고 나면 궁금증이 하나 생긴다.
if문 안의 증가/변경 코드들의 순서도 상관이 있을까?
sum == N 일때와 sum < N 일때는 endIdx를 증가시키고 sum을 변경하는데
sum > N 일때에는 sum을 먼저 변경하고 startIdx를 증가 시키고있다.
sum > N 일때 startIdx를 먼저 증가시키고 sum을 변경하면 답이 변경되어 출력된다.
왜일까?
sum > N 일 때 연속된 자연수에서 start_index를 삭제해야한다.
만약 위 코드와 다르게 start_index를 증가 시키고 sum을 변경 한다면 start_index를 삭제하는 효과를 기대하기 어렵다.
public class Main {
public static void main( String[] args ) throws IOException {
BufferedReader br = new BufferedReader( new InputStreamReader( System.in ) );
BufferedWriter bw = new BufferedWriter( new OutputStreamWriter( System.out ) );
StringTokenizer st = new StringTokenizer( br.readLine( ) );
long num = Integer.parseInt( st.nextToken() );
long count, startIdx, endIdx, sum;
count = startIdx = endIdx = sum = 1;
while ( endIdx != num ) {
if ( sum == num ) {
count++;
endIdx++;
sum += endIdx;
} else if ( sum > num ) {
sum -= startIdx;
startIdx++;
} else {
endIdx++;
sum += endIdx;
}
}
bw.write( count + "\n" );
bw.flush();
}
} // end