BOJ : 백준 2230 수고르기(JAVA)

백준 2230 수 고르기 자바 풀이 💡
알고리즘투포인터
avatar
2025.04.24
·
4 min read

문제

문제
N의 정수로 이루어진 수열 A[1], A[2], ... A[N]이 있다. 이 수열에서 두 수(같은 수일 수도 있음)를 골랐을 때 그 차이가 M 이상이면서 제일 작은 경우를 출력하라.
시간 제한 : 2초
메모리 제한 : 128MB

입력
N M
arr[0]
arr[1]
...
arr[N]

풀이

순차적인 자료 구조(array)를 사용할 때 포인터를 옮겨가며 답을 찾을 수 있을 것 같아 투 포인터 알고리즘을 사용하기로 했다. start = 0, end = length-1로 잡아야 할지, start = 0, end = 0으로 잡아야 할지를 고민했다.

start = 0, end = length-1 이면
M보다 클 때 end를 줄일 것이다. (end를 줄여야 M보다 작은 수가 나올 테니까)
생각해보면 아래와 같은 반례를 금방 떠올릴 수 있었다.
N = 5, M = 2
arr = 1 2 7 7 8 13

처음엔 end = 5고 start = 0이니까 10-1 = 9
여기서 점점 end를 줄여가다보면...
답은 13-7 혹은 7-1한 6이다
13-1 = 12
8-1 = 7
7-1 = 6
2-1 = 1 > M => start를 늘린다?
이러면 start == end니까 end++ start++...?
비효율적이다...
그리고 건너뛰는 숫자가 없어야 하는데, 위와 같은 방법으로는 건너뛰게 되는 값들이 생긴다.


그래서 start = 0, end = 0일 때로 구현해보았다.

생각한 플로우는 다음과 같다.

arr[end] - arr[start] < M ⇒ end++
arr[end] - arr[start] > M ⇒ start++
if start end ⇒ end++
if start - end
M ⇒ return(더 찾을 필요 X)

위의 플로우에 따라 작성한 코드는 이렇다.

import java.util.*;
import java.io.*;

public class Main {

	public static void main(String[] args) throws Exception {
		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[] arr = new int[N];
		for(int i = 0; i<N; i++) {
			arr[i] = Integer.parseInt(br.readLine());
		}
		
		Arrays.sort(arr);
		int res = Integer.MAX_VALUE;
		int start = 0;
		int end = 1;
		while(end<N) {
			int diff = arr[end] - arr[start];
			
			if(diff == M) {
				System.out.println(M);
				return;
			} else if(diff > M) {
				start++;
				res = Math.min(res, diff);
			} else {
				end++;
			}
			
			if(end == start) {	
				end++;
			}
		}
		System.out.println(res);
	}

}

문제를 풀며

특정 값을 찾는 문제라면 end = length-1로 시작하는 게 낫다는 걸 깨닫게 됐다.
왜냐면 조건에 따라 end를 줄이고 start를 늘리다보면 건너뛰게 되는 쌍이 있을 것이기 때문에... (1,n) (2,n) (3,n) ... (n-1, n) 이렇게 모든 쌍들을 일일히 확인하고 넘어가게 되는 게 아니라, (1, n) (2, n) (3, n-1) (3, n-2) 이런 식으로 조건에 만족하는 범위 내로만 탐색하므로 건너뛰게 되는 쌍들이 존재한다.

알고리즘은 애플리케이션에서 어떻게 돌아갈지와 스스로 반례를 찾아낼 때 제일 재미있는 것 같다🤓 뇌에 쥐 나는 감각 ㅎㅎ







- 컬렉션 아티클