[백준] 2470번 - 두 용액 (Gold 5)
업데이트:
문제 링크
문제 설명
수열이 주어져있을 때, 두 수의 합이 0에 가장 가깝도록 하는 수 두개를 출력하면 된다.
만약 방법이 여러가지라면, 그 중 한 가지를 아무거나 출력해도 된다.
정답 코드 및 설명
먼저 수열을 정렬하고, 순차적으로 탐색을 진행하였다.
첫 수를 정해두고, 이분탐색을 통해 첫 수와의 합이 가장 0에 가까운 두번째 수를 찾았다.
이렇게 얻어진 두 수의 합을 전부 비교하여 가장 작은 조합을 골랐다.
이 방식의 시간 복잡도는 $O(N\log N)$이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;
public class BOJ2470 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(br.readLine());
StringTokenizer st = new StringTokenizer(br.readLine());
int[] value = new int[n];
for (int i = 0; i < n; i++)
value[i] = Integer.parseInt(st.nextToken());
Arrays.sort(value);
int[] neutral = neutral(value, n);
bw.write(neutral[0] + " " + neutral[1]);
bw.close();
}
static int[] neutral(int[] value, int n) {
int first = 0, second = 1;
// 초기 두 용액의 특성값의 합의 절댓값
int valueSum = value[0] + value[1];
if (valueSum < 0)
valueSum = -valueSum;
// i와 이후 용액의 특성값의 합의 절댓값이 최소가 되도록 한다
for (int i = 0; i < n - 1; i++) {
// 이분탐색
int j = i + 1;
int end = n;
while (j + 1 < end) {
int mid = (j + end) / 2;
// 정확히 0이 되면 리턴
if (value[i] + value[mid] == 0)
return new int[] { value[i], value[mid] };
// 0보다 작은 최대의 원소 찾기
if (value[i] + value[mid] > 0)
end = mid;
if (value[i] + value[mid] < 0)
j = mid;
}
int vCan = value[i] + value[j];
if (vCan < 0)
vCan = -vCan;
if (j != n - 1 && value[i] + value[j + 1] < vCan) {
vCan = value[i] + value[j + 1];
j = j + 1;
}
if (vCan < valueSum) {
first = i;
second = j;
valueSum = vCan;
}
}
return new int[] { value[first], value[second] };
}
}
댓글남기기