Coding Test/백준

[백준] 2470 두 용액 - 자바

lsh2613 2023. 9. 12. 15:48

https://www.acmicpc.net/problem/2470

 

2470번: 두 용액

첫째 줄에는 전체 용액의 수 N이 입력된다. N은 2 이상 100,000 이하이다. 둘째 줄에는 용액의 특성값을 나타내는 N개의 정수가 빈칸을 사이에 두고 주어진다. 이 수들은 모두 -1,000,000,000 이상 1,000,00

www.acmicpc.net

문제 풀이

투 포인터 문제로 이진탐색을 생각하면 쉽게 해결할 수 있다.

두 용액을 섞었을 때 혼합값이 0에 가까워야 한다. 값을 비교하여 0보다 큰 수(양수)는 작아지도록, 0보다 작은 수(음수)는 커지도록 설정해주기 위해서 원하는 값을 참조할 수 있어야 한다. 따라서 이 로직을 적용시키기 위해 정렬을 먼저 해줘야 한다. (이진 탐색에서도 정렬을 먼저 하듯이)

숫자만 봐도 감이 올 것이다. 양쪽에 포인터 left, righr를 두고 이 두 값의 합이 0에 가까워지도록 포인터를 처리해주면 된다.

  • 값을 작게해주기 위해선 right를 왼쪽으로 움직이고
  • 값을 키우기 위해선 left를 오른쪽으로 옮긴다

단, 계속해서 위 로직이 적용되지는 않을 것이다. 포인터를 옮겼을 때 이전에 구한 값보다 0에서 멀리 떨어져 있다면, 즉 이전혼합값보다 포인터를 변경 후 혼합값의 절댓값이 더 크다면 위 로직을 종료하면된다.

코드

package 백준;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class b2470 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        int[] nums = Arrays.stream(br.readLine().split(" "))
                        .mapToInt(Integer::parseInt)
                        .toArray();

        Arrays.sort(nums);

        int left = 0, right = N - 1;
        int minSum = Integer.MAX_VALUE;
        int[] result = new int[2];

        while (left < right) {
            int sum = nums[left] + nums[right];
            if (Math.abs(sum) < minSum) {
                minSum = Math.abs(sum);
                result[0] = nums[left];
                result[1] = nums[right];
            }

            if (sum < 0) {
                left++;
            } else {
                right--;
            }
        }

        System.out.println(result[0] + " " + result[1]);
    }
}

\