여러 개의 숫자들 중에 합의 절댓값이 가장 작은 2개의 숫자를 찾는 문제이다.
투포인터를 사용할 수도 있고 이분탐색을 사용할 수도 있다.
뭘 사용하던 일단 정렬을 해야 한다.
단순히 오름차순으로 정렬한다.
values = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::valueOf).sorted().toArray();
int left = 0;
int right = N - 1;
int minAbs = Integer.MAX_VALUE;
int resultLeft = left;
int resultRight = right;
while (left < right) {
int abs = Math.abs(values[right] + values[left]);
if (abs < minAbs) {
minAbs = abs;
resultLeft = left;
resultRight = right;
}
left
와 right
는 양 끝으로 초기화하고,
둘이 만날 때까지 간격을 좁혀나간다.
이제 언제 left++
를 해야할지, 언제 right--
를 해야할지 조건을 만들어야 한다.
if (Math.abs(values[right] + values[left + 1]) < Math.abs(values[right - 1] + values[left])) {
left++;
}
else {
right--;
}
}
left++
와 right--
를 한 번씩 했다고 가정하고서 그 때의 합의 절댓값을 비교한다.
절댓값이 작은 쪽으로 이동시킨다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class _2470 {
private static int N;
private static int[] values;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());
values = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::valueOf).sorted().toArray();
int left = 0;
int right = N - 1;
int minAbs = Integer.MAX_VALUE;
int resultLeft = left;
int resultRight = right;
while (left < right) {
// printStatus(left, right);
int abs = Math.abs(values[right] + values[left]);
if (abs < minAbs) {
minAbs = abs;
resultLeft = left;
resultRight = right;
}
if (Math.abs(values[right] + values[left + 1]) < Math.abs(values[right - 1] + values[left])) {
left++;
}
else {
right--;
}
}
System.out.printf("%d %d\n", values[resultLeft], values[resultRight]);
}
private static void printStatus(int left, int right) {
for (int value : values) {
System.out.printf("%5d", value);
}
System.out.println();
for (int i=0; i<N; i++) {
System.out.printf("%5c", i==left || i==right ? '^' : ' ');
}
System.out.println();
}
}