Algorithm
[백준] 2467: 용액 JAVA
하다보면 되겠지
2023. 1. 18. 16:07
접근
두 개의 용액을 섞어서 0에 가장 가까운 값을 만들고자 한다면, 결국 음수와 양수의 절댓값이 가장 비슷한 두 수를 더해야 한다. 이를 위해서 입력값을 저장하고 오름차순으로 정렬한 뒤, 가장 작은 수(배열의 왼쪽)와 가장 큰 수(배열의 오른쪽)를 가리키는 포인터 두 개를 통해 그 합을 비교한다.
left와 right는 배열의 각 끝을 가리키며, ansLeft와 ansRight는 두 용액의 합이 0에 가장 가까운 두 수를 가리킨다. minVal은 그 합의 절댓값에 해당한다. 용액의 특성값은 -1,000,000,000 ~ 1,000,000,000 사이에 해당하므로, 최악의 경우에는 그 합이 1,000,000,000 * 2가 될 수도 있다. 따라서 이를 MAX_VAL이라고 미리 선언해두어 minVal값을 초기화했다.
두 포인터가 어긋나지 않을 때까지, 즉 left가 right보다 작을 때까지 반복하며 두 용액을 합해본다. 이때 합한 특성값이 양수라면 정렬된 배열에서 더 큰 수를 가리키고 있는 right를 줄이고, 음수라면 작은 수를 가리키고 있는 left를 올린다.
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
static int MAX_VAL = 1000000000 * 2;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 입력값 저장 후 정렬
int n = Integer.parseInt(br.readLine());
ArrayList<Integer> arr = new ArrayList<>();
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++)
arr.add(Integer.parseInt(st.nextToken()));
Collections.sort(arr);
// 투 포인터 적용
int left = 0, right = n - 1;
int ansLeft = left, ansRight = right;
int minVal = MAX_VAL; // 가장 최악의 경우
while(left < right){
int val = arr.get(left) + arr.get(right);
if(Math.abs(val) <= minVal){
minVal = Math.abs(val);
ansLeft = left;
ansRight = right;
}
if(val == 0) break;
else if(val > 0) right--;
else left++;
}
System.out.println(arr.get(ansLeft) + " " + arr.get(ansRight));
}
}